{
  "cells": [
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "b7b7bbeff6237c20",
      "metadata": {
        "ExecuteTime": {
          "end_time": "2025-07-11T07:06:05.692112Z",
          "start_time": "2025-07-11T07:05:59.543386Z"
        },
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "b7b7bbeff6237c20",
        "outputId": "a4d8ae68-8890-4fa3-8f4f-62da14479467"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "sys.version_info(major=3, minor=12, micro=3, releaselevel='final', serial=0)\n",
            "matplotlib 3.10.0\n",
            "numpy 1.26.4\n",
            "pandas 2.2.3\n",
            "sklearn 1.6.0\n",
            "torch 2.5.1+cpu\n",
            "cpu\n"
          ]
        }
      ],
      "source": [
        "import matplotlib as mpl\n",
        "import matplotlib.pyplot as plt\n",
        "%matplotlib inline\n",
        "import numpy as np\n",
        "import sklearn\n",
        "import pandas as pd\n",
        "import os\n",
        "import sys\n",
        "import time\n",
        "from tqdm.auto import tqdm\n",
        "import torch\n",
        "import torch.nn as nn\n",
        "import torch.nn.functional as F\n",
        "\n",
        "print(sys.version_info)\n",
        "for module in mpl, np, pd, sklearn, torch:\n",
        "    print(module.__name__, module.__version__)\n",
        "\n",
        "device = torch.device(\"cuda:0\") if torch.cuda.is_available() else torch.device(\"cpu\")\n",
        "print(device)\n",
        "\n",
        "seed = 42\n",
        "torch.manual_seed(seed)\n",
        "torch.cuda.manual_seed_all(seed)\n",
        "np.random.seed(seed)\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "5a60b154",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Total samples: 118964\n",
            "Training samples: 101119\n",
            "Validation samples: 5948\n",
            "Test samples: 11897\n"
          ]
        }
      ],
      "source": [
        "# Read the spa.txt file and process the data\n",
        "import random\n",
        "\n",
        "# Function to split data into train, validation, and test sets\n",
        "def split_data(data, train_ratio=0.85, val_ratio=0.05, test_ratio=0.1):\n",
        "    \n",
        "    # Set random seed for reproducibility\n",
        "    random.seed(seed)\n",
        "    # Ensure consistent data splits across runs\n",
        "    # Shuffle the data\n",
        "    random.shuffle(data)\n",
        "    \n",
        "    # Calculate split indices\n",
        "    train_end = int(len(data) * train_ratio)\n",
        "    val_end = train_end + int(len(data) * val_ratio)\n",
        "    \n",
        "    # Split the data\n",
        "    train_data = data[:train_end]\n",
        "    val_data = data[train_end:val_end]\n",
        "    test_data = data[val_end:]\n",
        "    \n",
        "    return train_data, val_data, test_data\n",
        "\n",
        "# Read the spa.txt file\n",
        "with open(\"spa.txt\", \"r\", encoding=\"utf-8\") as f:\n",
        "    lines = f.readlines()\n",
        "\n",
        "# Parse the data (tab-separated English and Spanish sentences)\n",
        "data = []\n",
        "for line in lines:\n",
        "    line = line.strip()\n",
        "    if line:\n",
        "        parts = line.split(\"\\t\")\n",
        "        if len(parts) == 2:\n",
        "            en, sp = parts\n",
        "            data.append((en, sp))\n",
        "\n",
        "# Split the data\n",
        "train_data, val_data, test_data = split_data(data)\n",
        "\n",
        "# Create output files\n",
        "for dataset, name in [(train_data, \"train\"), (val_data, \"val\"), (test_data, \"test\")]:\n",
        "    # Write English sentences\n",
        "    with open(f\"wmt16/{name}.en\", \"w\", encoding=\"utf-8\") as f:\n",
        "        for en, _ in dataset:\n",
        "            f.write(en + \"\\n\")\n",
        "    \n",
        "    # Write Spanish sentences\n",
        "    with open(f\"wmt16/{name}.es\", \"w\", encoding=\"utf-8\") as f:\n",
        "        for _, sp in dataset:\n",
        "            f.write(sp + \"\\n\")\n",
        "\n",
        "# Print statistics\n",
        "print(f\"Total samples: {len(data)}\")\n",
        "print(f\"Training samples: {len(train_data)}\")\n",
        "print(f\"Validation samples: {len(val_data)}\")\n",
        "print(f\"Test samples: {len(test_data)}\")\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a61058c1",
      "metadata": {
        "id": "a61058c1"
      },
      "source": [
        "# MosesTokenizer预处理 subword-nmt分词"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 7,
      "id": "cfHuRRtwArkM",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "cfHuRRtwArkM",
        "outputId": "8662c775-a184-4b6e-cfc8-694421bf77fa"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Collecting sacremoses\n",
            "  Downloading sacremoses-0.1.1-py3-none-any.whl.metadata (8.3 kB)\n",
            "Collecting subword-nmt\n",
            "  Downloading subword_nmt-0.3.8-py3-none-any.whl.metadata (9.2 kB)\n",
            "Requirement already satisfied: regex in /usr/local/lib/python3.11/dist-packages (from sacremoses) (2024.11.6)\n",
            "Requirement already satisfied: click in /usr/local/lib/python3.11/dist-packages (from sacremoses) (8.2.1)\n",
            "Requirement already satisfied: joblib in /usr/local/lib/python3.11/dist-packages (from sacremoses) (1.5.1)\n",
            "Requirement already satisfied: tqdm in /usr/local/lib/python3.11/dist-packages (from sacremoses) (4.67.1)\n",
            "Collecting mock (from subword-nmt)\n",
            "  Downloading mock-5.2.0-py3-none-any.whl.metadata (3.1 kB)\n",
            "Downloading sacremoses-0.1.1-py3-none-any.whl (897 kB)\n",
            "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m897.5/897.5 kB\u001b[0m \u001b[31m18.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[?25hDownloading subword_nmt-0.3.8-py3-none-any.whl (27 kB)\n",
            "Downloading mock-5.2.0-py3-none-any.whl (31 kB)\n",
            "Installing collected packages: sacremoses, mock, subword-nmt\n",
            "Successfully installed mock-5.2.0 sacremoses-0.1.1 subword-nmt-0.3.8\n"
          ]
        }
      ],
      "source": [
        "!pip install sacremoses subword-nmt"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "id": "initial_id",
      "metadata": {
        "ExecuteTime": {
          "end_time": "2025-07-11T07:30:43.221658Z",
          "start_time": "2025-07-11T07:30:27.977023Z"
        },
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "collapsed": true,
        "id": "initial_id",
        "outputId": "9e94a9bc-0f52-42a6-ba50-60b1a0a9a79d"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "[train] 源语言文本分词完成\n",
            "[train] 目标语言文本分词完成\n",
            "[val] 源语言文本分词完成\n",
            "[val] 目标语言文本分词完成\n",
            "[test] 源语言文本分词完成\n",
            "[test] 目标语言文本分词完成\n",
            "Finished applying bpe to train files.\n",
            "Finished applying bpe to val files.\n",
            "Finished applying bpe to test files.\n"
          ]
        },
        {
          "name": "stderr",
          "output_type": "stream",
          "text": [
            "\n",
            "  0%|          | 0/30000 [00:00<?, ?it/s]\n",
            "  0%|          | 24/30000 [00:00<02:07, 234.67it/s]\n",
            "  0%|          | 57/30000 [00:00<01:44, 285.63it/s]\n",
            "  0%|          | 108/30000 [00:00<01:17, 386.40it/s]\n",
            "  1%|          | 200/30000 [00:00<00:50, 593.57it/s]\n",
            "  1%|1         | 301/30000 [00:00<00:40, 737.82it/s]\n",
            "  1%|1         | 430/30000 [00:00<00:32, 921.33it/s]\n",
            "  2%|1         | 572/30000 [00:00<00:27, 1081.29it/s]\n",
            "  2%|2         | 745/30000 [00:00<00:22, 1283.72it/s]\n",
            "  3%|3         | 945/30000 [00:00<00:19, 1503.90it/s]\n",
            "  4%|3         | 1121/30000 [00:01<00:18, 1578.93it/s]\n",
            "  4%|4         | 1331/30000 [00:01<00:16, 1732.30it/s]\n",
            "  5%|5         | 1573/30000 [00:01<00:14, 1936.14it/s]\n",
            "  6%|6         | 1872/30000 [00:01<00:12, 2250.01it/s]\n",
            "  7%|7         | 2198/30000 [00:01<00:10, 2548.22it/s]\n",
            "  9%|8         | 2600/30000 [00:01<00:09, 2987.66it/s]\n",
            " 10%|#         | 3141/30000 [00:01<00:07, 3705.80it/s]\n",
            " 13%|#2        | 3861/30000 [00:01<00:05, 4750.42it/s]\n",
            " 14%|#4        | 4337/30000 [00:01<00:07, 3243.59it/s]\n",
            " 16%|#5        | 4726/30000 [00:02<00:09, 2639.29it/s]\n",
            " 17%|#6        | 5050/30000 [00:02<00:10, 2421.91it/s]\n",
            " 18%|#7        | 5334/30000 [00:02<00:10, 2306.17it/s]\n",
            " 19%|#8        | 5593/30000 [00:02<00:10, 2284.03it/s]\n",
            " 19%|#9        | 5841/30000 [00:02<00:10, 2298.33it/s]\n",
            " 20%|##        | 6101/30000 [00:02<00:10, 2366.17it/s]\n",
            " 21%|##1       | 6390/30000 [00:02<00:09, 2499.42it/s]\n",
            " 22%|##2       | 6703/30000 [00:03<00:08, 2666.28it/s]\n",
            " 24%|##3       | 7063/30000 [00:03<00:07, 2921.26it/s]\n",
            " 25%|##4       | 7495/30000 [00:03<00:06, 3309.14it/s]\n",
            " 27%|##6       | 8072/30000 [00:03<00:05, 4004.70it/s]\n",
            " 28%|##8       | 8481/30000 [00:03<00:06, 3417.75it/s]\n",
            " 29%|##9       | 8844/30000 [00:03<00:08, 2551.58it/s]\n",
            " 30%|###       | 9144/30000 [00:03<00:09, 2226.80it/s]\n",
            " 31%|###1      | 9402/30000 [00:04<00:09, 2079.55it/s]\n",
            " 32%|###2      | 9634/30000 [00:04<00:10, 2023.63it/s]\n",
            " 33%|###2      | 9852/30000 [00:04<00:10, 2009.37it/s]\n",
            " 34%|###3      | 10064/30000 [00:04<00:09, 2016.78it/s]\n",
            " 34%|###4      | 10274/30000 [00:04<00:09, 2034.10it/s]\n",
            " 35%|###4      | 10499/30000 [00:04<00:09, 2088.66it/s]\n",
            " 36%|###5      | 10736/30000 [00:04<00:08, 2160.04it/s]\n",
            " 37%|###6      | 10996/30000 [00:04<00:08, 2276.72it/s]\n",
            " 38%|###7      | 11270/30000 [00:04<00:07, 2408.32it/s]\n",
            " 38%|###8      | 11521/30000 [00:05<00:07, 2435.94it/s]\n",
            " 39%|###9      | 11844/30000 [00:05<00:06, 2661.75it/s]\n",
            " 41%|####      | 12227/30000 [00:05<00:05, 3001.67it/s]\n",
            " 42%|####2     | 12688/30000 [00:05<00:04, 3467.02it/s]\n",
            " 45%|####4     | 13374/30000 [00:05<00:03, 4469.92it/s]\n",
            " 46%|####6     | 13824/30000 [00:05<00:06, 2510.99it/s]\n",
            " 47%|####7     | 14176/30000 [00:06<00:07, 2140.19it/s]\n",
            " 48%|####8     | 14467/30000 [00:06<00:07, 2014.30it/s]\n",
            " 49%|####9     | 14721/30000 [00:06<00:07, 1929.25it/s]\n",
            " 50%|####9     | 14950/30000 [00:06<00:07, 1906.85it/s]\n",
            " 51%|#####     | 15165/30000 [00:06<00:07, 1896.84it/s]\n",
            " 51%|#####1    | 15372/30000 [00:06<00:07, 1927.19it/s]\n",
            " 52%|#####1    | 15579/30000 [00:06<00:07, 1955.86it/s]\n",
            " 53%|#####2    | 15793/30000 [00:06<00:07, 2001.40it/s]\n",
            " 53%|#####3    | 16022/30000 [00:06<00:06, 2073.57it/s]\n",
            " 54%|#####4    | 16279/30000 [00:07<00:06, 2209.13it/s]\n",
            " 55%|#####5    | 16548/30000 [00:07<00:05, 2343.91it/s]\n",
            " 56%|#####6    | 16861/30000 [00:07<00:05, 2568.46it/s]\n",
            " 57%|#####7    | 17203/30000 [00:07<00:04, 2810.85it/s]\n",
            " 59%|#####8    | 17597/30000 [00:07<00:03, 3136.15it/s]\n",
            " 60%|######    | 18095/30000 [00:07<00:03, 3670.53it/s]\n",
            " 63%|######2   | 18787/30000 [00:07<00:03, 3579.02it/s]\n",
            " 64%|######3   | 19150/30000 [00:08<00:04, 2274.43it/s]\n",
            " 65%|######4   | 19437/30000 [00:08<00:05, 1877.02it/s]\n",
            " 66%|######5   | 19673/30000 [00:08<00:06, 1702.12it/s]\n",
            " 66%|######6   | 19876/30000 [00:08<00:06, 1598.60it/s]\n",
            " 67%|######6   | 20057/30000 [00:08<00:06, 1541.82it/s]\n",
            " 67%|######7   | 20224/30000 [00:08<00:06, 1466.92it/s]\n",
            " 68%|######7   | 20378/30000 [00:09<00:06, 1474.54it/s]\n",
            " 68%|######8   | 20531/30000 [00:09<00:06, 1471.03it/s]\n",
            " 69%|######8   | 20698/30000 [00:09<00:06, 1516.48it/s]\n",
            " 70%|######9   | 20869/30000 [00:09<00:05, 1563.83it/s]\n",
            " 70%|#######   | 21047/30000 [00:09<00:05, 1621.17it/s]\n",
            " 71%|#######   | 21228/30000 [00:09<00:05, 1672.16it/s]\n",
            " 71%|#######1  | 21426/30000 [00:09<00:04, 1755.25it/s]\n",
            " 72%|#######2  | 21610/30000 [00:09<00:04, 1775.07it/s]\n",
            " 73%|#######2  | 21807/30000 [00:09<00:04, 1828.47it/s]\n",
            " 73%|#######3  | 22015/30000 [00:10<00:04, 1899.52it/s]\n",
            " 74%|#######4  | 22233/30000 [00:10<00:03, 1981.95it/s]\n",
            " 75%|#######4  | 22472/30000 [00:10<00:03, 2100.33it/s]\n",
            " 76%|#######5  | 22731/30000 [00:10<00:03, 2240.64it/s]\n",
            " 77%|#######6  | 23009/30000 [00:10<00:02, 2400.89it/s]\n",
            " 78%|#######7  | 23308/30000 [00:10<00:02, 2569.62it/s]\n",
            " 79%|#######8  | 23660/30000 [00:10<00:02, 2841.97it/s]\n",
            " 80%|########  | 24077/30000 [00:10<00:01, 3235.02it/s]\n",
            " 82%|########2 | 24645/30000 [00:10<00:01, 3959.63it/s]\n",
            " 84%|########3 | 25077/30000 [00:10<00:01, 3481.84it/s]\n",
            " 85%|########4 | 25438/30000 [00:11<00:02, 1856.64it/s]\n",
            " 86%|########5 | 25716/30000 [00:11<00:02, 1470.11it/s]\n",
            " 86%|########6 | 25937/30000 [00:11<00:03, 1315.41it/s]\n",
            " 87%|########7 | 26120/30000 [00:12<00:03, 1236.16it/s]\n",
            " 88%|########7 | 26278/30000 [00:12<00:03, 1185.50it/s]\n",
            " 88%|########8 | 26419/30000 [00:12<00:03, 1133.88it/s]\n",
            " 88%|########8 | 26547/30000 [00:12<00:03, 1114.34it/s]\n",
            " 89%|########8 | 26668/30000 [00:12<00:02, 1119.67it/s]\n",
            " 89%|########9 | 26788/30000 [00:12<00:02, 1137.10it/s]\n",
            " 90%|########9 | 26911/30000 [00:12<00:02, 1157.56it/s]\n",
            " 90%|######### | 27034/30000 [00:12<00:02, 1172.96it/s]\n",
            " 91%|######### | 27162/30000 [00:13<00:02, 1201.01it/s]\n",
            " 91%|######### | 27295/30000 [00:13<00:02, 1232.82it/s]\n",
            " 91%|#########1| 27438/30000 [00:13<00:01, 1287.40it/s]\n",
            " 92%|#########1| 27577/30000 [00:13<00:01, 1315.38it/s]\n",
            " 92%|#########2| 27715/30000 [00:13<00:01, 1333.62it/s]\n",
            " 93%|#########2| 27858/30000 [00:13<00:01, 1358.92it/s]\n",
            " 93%|#########3| 28002/30000 [00:13<00:01, 1382.60it/s]\n",
            " 94%|#########3| 28157/30000 [00:13<00:01, 1431.04it/s]\n",
            " 94%|#########4| 28311/30000 [00:13<00:01, 1462.71it/s]\n",
            " 95%|#########4| 28481/30000 [00:13<00:00, 1531.25it/s]\n",
            " 96%|#########5| 28654/30000 [00:14<00:00, 1587.55it/s]\n",
            " 96%|#########6| 28827/30000 [00:14<00:00, 1627.54it/s]\n",
            " 97%|#########6| 29006/30000 [00:14<00:00, 1671.22it/s]\n",
            " 97%|#########7| 29201/30000 [00:14<00:00, 1677.05it/s]\n",
            " 98%|#########8| 29417/30000 [00:14<00:00, 1813.62it/s]\n",
            " 99%|#########8| 29637/30000 [00:14<00:00, 1924.21it/s]\n",
            "100%|#########9| 29879/30000 [00:14<00:00, 2066.62it/s]\n",
            "100%|##########| 30000/30000 [00:14<00:00, 2035.31it/s]\n"
          ]
        }
      ],
      "source": [
        "!sh data_multi30k_es_en.sh wmt16 wmt16 es en"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 41,
      "id": "1acf1f44",
      "metadata": {
        "ExecuteTime": {
          "end_time": "2025-07-11T08:03:52.736243Z",
          "start_time": "2025-07-11T08:03:52.535567Z"
        },
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 702
        },
        "id": "1acf1f44",
        "outputId": "5dc24a6c-d540-4e44-e648-125b0a2b8cab"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Total sentences: 101119\n",
            "Min length: 4\n",
            "Max length: 293\n",
            "Mean length: 34.71\n",
            "Median length: 32.0\n"
          ]
        },
        {
          "data": {
            "image/png": "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",
            "text/plain": [
              "<Figure size 1000x600 with 1 Axes>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "# Read the training source file and analyze sentence lengths\n",
        "with open(\"wmt16/train_src.bpe\", \"r\", encoding=\"utf8\") as file:\n",
        "    lines = file.readlines()\n",
        "\n",
        "# Split each line and calculate lengths\n",
        "lengths = [len(line.strip()) for line in lines]\n",
        "\n",
        "# Create a histogram of sentence lengths\n",
        "plt.figure(figsize=(10, 6))\n",
        "plt.hist(lengths, bins=50, alpha=0.7, color='blue')\n",
        "plt.xlabel('Sentence Length (number of tokens)')\n",
        "plt.ylabel('Frequency')\n",
        "plt.title('Distribution of Sentence Lengths in Training Data')\n",
        "plt.grid(True, alpha=0.3)\n",
        "\n",
        "# Add some statistics as text\n",
        "plt.axvline(np.mean(lengths), color='r', linestyle='dashed', linewidth=1, label=f'Mean: {np.mean(lengths):.2f}')\n",
        "plt.axvline(np.median(lengths), color='g', linestyle='dashed', linewidth=1, label=f'Median: {np.median(lengths):.2f}')\n",
        "plt.legend()\n",
        "\n",
        "# Display some statistics\n",
        "print(f\"Total sentences: {len(lengths)}\")\n",
        "print(f\"Min length: {min(lengths)}\")\n",
        "print(f\"Max length: {max(lengths)}\")\n",
        "print(f\"Mean length: {np.mean(lengths):.2f}\")\n",
        "print(f\"Median length: {np.median(lengths)}\")\n",
        "\n",
        "plt.tight_layout()\n",
        "plt.show()\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 11,
      "id": "f7c22d1a",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 702
        },
        "id": "f7c22d1a",
        "outputId": "3d69a82f-5503-4d60-d5a6-f0b04b162748"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Total sentences: 29000\n",
            "Min length: 4\n",
            "Max length: 41\n",
            "Mean length: 13.25\n",
            "Median length: 13.0\n"
          ]
        },
        {
          "data": {
            "image/png": "iVBORw0KGgoAAAANSUhEUgAAA90AAAJOCAYAAACqS2TfAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjAsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvlHJYcgAAAAlwSFlzAAAPYQAAD2EBqD+naQAAkjBJREFUeJzs3Xd8FHX+x/H3puymFyCFQIBQpClS9CA2EJAgGPXADlLEHjwB2w89FfROFKVYUM7zBD1FBc8CNooCHggqYJSidAglCaGlkb7z+4PLyJJkhc0uybKv5+ORxzqf+X5nvjPfzMon35n5WgzDMAQAAAAAANzOr64bAAAAAADA2YqkGwAAAAAADyHpBgAAAADAQ0i6AQAAAADwEJJuAAAAAAA8hKQbAAAAAAAPIekGAAAAAMBDSLoBAAAAAPAQkm4AAAAAADyEpBsAamHChAmyWCxnZF+9evVSr169zOVly5bJYrHoww8/PCP7HzFihFq0aHFG9uWqgoIC3X777YqPj5fFYtGYMWPqukmox3bt2iWLxaIXXnjBY/s4k98R7jJ79mxZLBbt2rXrtOtWfi8tW7bM7e0CAG9F0g0A/1P5D83Kn6CgICUkJCglJUUvvfSS8vPz3bKf/fv3a8KECUpPT3fL9typPrftVDzzzDOaPXu27rnnHv373//WrbfeWmPZ0tJSvfjii+rSpYsiIiIUFRWljh076s4779Rvv/3m0XbOmTNH06dP9+g+zqRevXrp3HPPretm1OiLL77QhAkT6roZtdarVy+H76iafs6GY3WFJ7/Dv/vuO02YMEFHjx51X4MB+AyLYRhGXTcCAOqD2bNna+TIkXrqqaeUlJSksrIyZWVladmyZVq8eLGaNWum+fPnq1OnTmad8vJylZeXKygo6JT3s2bNGl144YWaNWuWRowYccr1SktLJUlWq1XS8RGlyy+/XPPmzdN11113yttxtW1lZWWy2+2y2Wxu2Zcn9OjRQwEBAVqxYsUflk1NTdWXX36pm2++WcnJySorK9Nvv/2mzz77TE8//fRp9c3puuqqq7RhwwaXRhLro169eungwYPasGFDXTelWqNHj9aMGTN08j95du3apaSkJD3//PN68MEHPbJvV74jarJ48WJlZ2ebyz/++KNeeuklPfroo2rfvr0Z79Spk8P31OmqqKhQWVmZbDbbaY/S2+12lZaWymq1ys/vzI7tuPIdfqpeeOEFPfTQQ9q5c2e9v+MHQP0TUNcNAID65sorr9QFF1xgLo8fP17ffPONrrrqKl199dX69ddfFRwcLEkKCAhQQIBnv0qPHTumkJAQM9muK4GBgXW6/1Nx4MABdejQ4Q/L/fjjj/rss8/097//XY8++qjDuldeeYXRLLiNO78jrrjiCofloKAgvfTSS7riiiscHj05WWFhoUJDQ095P/7+/vL393epjX5+fm75A0NtnM53OACcCdxeDgCnoHfv3nr88ce1e/duvfPOO2a8uuc1Fy9erEsuuURRUVEKCwtT27ZtzcRu2bJluvDCCyVJI0eONG+DnD17tqTfb9Ndu3atLrvsMoWEhJh1T36mu1JFRYUeffRRxcfHKzQ0VFdffbX27NnjUKZFixbVjtyeuM0/alt1z3QXFhbqgQceUGJiomw2m9q2basXXnihyoiixWLR6NGj9cknn+jcc8+VzWZTx44d9dVXX1V/wk9y4MABjRo1SnFxcQoKCtL555+vt956y1xf+Rzpzp079fnnn5ttr2kkefv27ZKkiy++uMo6f39/NWzY0CG2b98+3XbbbYqLizPb/uabbzqUqWzD3Llz9fe//11NmzZVUFCQ+vTpo23btpnlevXqpc8//1y7d+8223nieS0pKdGTTz6p1q1by2azKTExUQ8//LBKSkpcPqf79u3TqFGjlJCQIJvNpqSkJN1zzz3m3ROSdPToUY0ZM8bsy9atW+u5556T3W6v9hy64ssvv9Sll16q0NBQhYeHa+DAgdq4caNDmREjRigsLEz79u3Ttddeq7CwMMXExOjBBx9URUWFQ9lDhw7p1ltvNR8PGD58uH7++ecqv7czZswwz1nlz8lef/11tWrVSjabTRdeeKF+/PFHh/VZWVkaOXKkmjZtKpvNpsaNG+uaa675w7sVqvuOqO31cCr727Rpk2655RZFR0frkksukST98ssvGjFihFq2bKmgoCDFx8frtttu06FDhxy2Ud0z3S1atNBVV12lFStW6E9/+pOCgoLUsmVLvf322w51q3umu/J7bdOmTbr88ssVEhKiJk2aaPLkyVXav3v3bl199dUKDQ1VbGysxo4dq4ULF9b6OfGavsNP5ZxMmDBBDz30kCQpKSmpyvfLrFmz1Lt3b8XGxspms6lDhw567bXXXG4rgLMPI90AcIpuvfVWPfroo1q0aJHuuOOOasts3LhRV111lTp16qSnnnpKNptN27Zt08qVKyVJ7du311NPPaUnnnhCd955py699FJJ0kUXXWRu49ChQ7ryyit10003aejQoYqLi3Parr///e+yWCx65JFHdODAAU2fPl19+/ZVenr6aY3mnErbTmQYhq6++motXbpUo0aNUufOnbVw4UI99NBD2rdvn6ZNm+ZQfsWKFfroo4907733Kjw8XC+99JIGDx6sjIyMKknuiYqKitSrVy9t27ZNo0ePVlJSkubNm6cRI0bo6NGjuv/++9W+fXv9+9//1tixY9W0aVM98MADkqSYmJhqt9m8eXNJ0rvvvquLL77Y6Uhkdna2evToYSZKMTEx+vLLLzVq1Cjl5eVVeVnbs88+Kz8/Pz344IPKzc3V5MmTNWTIEH3//feSpMcee0y5ubnau3eveY7CwsIkHb819+qrr9aKFSt05513qn379lq/fr2mTZumLVu26JNPPjntc7p//3796U9/0tGjR3XnnXeqXbt22rdvnz788EMdO3ZMVqtVx44dU8+ePbVv3z7dddddatasmb777juNHz9emZmZbnn+/N///reGDx+ulJQUPffcczp27Jhee+01XXLJJfrpp58c/vBQUVGhlJQUde/eXS+88IKWLFmiKVOmqFWrVrrnnnvMc5WamqoffvhB99xzj9q1a6dPP/1Uw4cPd9jvXXfdpf3792vx4sX697//XW3b5syZo/z8fN11112yWCyaPHmyBg0apB07dph3eAwePFgbN27UfffdpxYtWujAgQNavHixMjIyXLrd2NXr4VRdf/31atOmjZ555hnzj2CLFy/Wjh07NHLkSMXHx2vjxo16/fXXtXHjRq1evfoPbyXftm2brrvuOo0aNUrDhw/Xm2++qREjRqhbt27q2LGj07pHjhxR//79NWjQIN1www368MMP9cgjj+i8887TlVdeKen4H/F69+6tzMxM3X///YqPj9ecOXO0dOnSWp8Pqfrv8FM5J4MGDdKWLVv03nvvadq0aWrUqJGk379fXnvtNXXs2FFXX321AgICtGDBAt17772y2+1KS0tzS9sBeDkDAGAYhmHMmjXLkGT8+OOPNZaJjIw0unTpYi4/+eSTxolfpdOmTTMkGTk5OTVu48cffzQkGbNmzaqyrmfPnoYkY+bMmdWu69mzp7m8dOlSQ5LRpEkTIy8vz4zPnTvXkGS8+OKLZqx58+bG8OHD/3Cbzto2fPhwo3nz5ubyJ598Ykgy/va3vzmUu+666wyLxWJs27bNjEkyrFarQ+znn382JBkvv/xylX2daPr06YYk45133jFjpaWlRnJyshEWFuZw7M2bNzcGDhzodHuGYRh2u90813FxccbNN99szJgxw9i9e3eVsqNGjTIaN25sHDx40CF+0003GZGRkcaxY8cMw/i9P9q3b2+UlJSY5V588UVDkrF+/XozNnDgQIdzWenf//634efnZ/z3v/91iM+cOdOQZKxcudKMneo5HTZsmOHn51ft77XdbjcMwzCefvppIzQ01NiyZYvD+v/7v/8z/P39jYyMjCp1T9SzZ0+jY8eONa7Pz883oqKijDvuuMMhnpWVZURGRjrEhw8fbkgynnrqKYeyXbp0Mbp162Yu/+c//zEkGdOnTzdjFRUVRu/evav8DqelpRnV/ZNn586dhiSjYcOGxuHDh834p59+akgyFixYYBiGYRw5csSQZDz//PNOz0N1Tv6OMIzaXQ8nmjdvniHJWLp0aZX93XzzzVXKV/6unui9994zJBnffvutGav8Lty5c6cZa968eZVyBw4cMGw2m/HAAw+Yscrr4MQ2VV5rb7/9thkrKSkx4uPjjcGDB5uxKVOmGJKMTz75xIwVFRUZ7dq1q7LN6rjyHX6q5+T555+vck6cbSMlJcVo2bKl0/YC8B3cXg4ApyEsLMzpG3CjoqIkSZ9++qnLt+XabDaNHDnylMsPGzZM4eHh5vJ1112nxo0b64svvnBp/6fqiy++kL+/v/7yl784xB944AEZhqEvv/zSId63b1+1atXKXO7UqZMiIiK0Y8eOP9xPfHy8br75ZjMWGBiov/zlLyooKNDy5ctPu+0Wi0ULFy7U3/72N0VHR+u9995TWlqamjdvrhtvvNF8ptswDP3nP/9RamqqDMPQwYMHzZ+UlBTl5uZq3bp1DtseOXKkw/P3lXcM/NFxStK8efPUvn17tWvXzmFfvXv3lqQqI35/dE7tdrs++eQTpaamOjzjeuJ5qNzvpZdequjoaIf99u3bVxUVFfr222//sO3OLF68WEePHtXNN9/ssH1/f39179692pHMu+++22H50ksvdTiHX331lQIDAx3uOvHz83NpZPHGG29UdHS0w76k3/ssODhYVqtVy5Yt05EjR057+9Vx9Xo4VSefP0kOd74UFxfr4MGD6tGjhyRV+T2uTocOHcxzIx0f6W3btu0ptTksLExDhw41l61Wq/70pz9V6dMmTZro6quvNmNBQUE13lnkipO/w2t7Tk7eRm5urg4ePKiePXtqx44dys3NdVPLAXgzbi8HgNNQUFCg2NjYGtffeOONeuONN3T77bfr//7v/9SnTx8NGjRI11133Sm/ybdJkyan9dK0Nm3aOCxbLBa1bt3a42/G3r17txISEhwSfknmW5R3797tEG/WrFmVbURHR/9hErN79261adOmyvmraT+nymaz6bHHHtNjjz2mzMxMLV++XC+++KLmzp2rwMBAvfPOO8rJydHRo0f1+uuv6/XXX692OwcOHHBYPvk4K5O5U0nWtm7dql9//bXG2+L/aF+V+6vcV05OjvLy8v5wOq+tW7fql19+OeX9nq6tW7dKkvnHg5NFREQ4LAcFBVVpy8m/K7t371bjxo0VEhLiUK5169an3b4/6jObzabnnntODzzwgOLi4tSjRw9dddVVGjZsmOLj4097f9Xts3K/7krqk5KSqsQOHz6siRMn6v3336/Sp6eSHNamzU2bNq1y+3p0dLR++eUXc3n37t1q1apVlXKu9GlNTv4Or+05kaSVK1fqySef1KpVq3Ts2LEq24iMjKx9wwF4NZJuADhFe/fuVW5urtN/AAYHB+vbb7/V0qVL9fnnn+urr77SBx98oN69e2vRokWn9EZgT7xVt6ZnNSsqKlx+S/Hpqmk/Rj2YubJx48a66aabNHjwYHXs2FFz587V7NmzzbsVhg4dWuVZ4UonTz9Um+O02+0677zzNHXq1GrXJyYmum1fJ+/3iiuu0MMPP1zt+nPOOee0tlfd9qXjz3VXl6Se/Ez9mfqd/KP9nXgex4wZo9TUVH3yySdauHChHn/8cU2aNEnffPONunTp4pF91kZ13yM33HCDvvvuOz300EPq3LmzwsLCZLfb1b9//1O6M6c2ba4P13913+G1PSfbt29Xnz591K5dO02dOlWJiYmyWq364osvNG3aNLe+iBCA9yLpBoBTVPkSppSUFKfl/Pz81KdPH/Xp00dTp07VM888o8cee0xLly5V3759T3ve2z9SOYpYyTAMbdu2zSEZjI6OrnYarN27d6tly5bm8um0rXnz5lqyZIny8/MdRrt/++03c707NG/eXL/88ovsdrvDaLe79yMdv229U6dO2rp1qw4ePKiYmBiFh4eroqJCffv2ddt+ajrPrVq10s8//6w+ffq45fckJiZGERERfzh/dqtWrVRQUODWYzx5+5IUGxvrtn00b95cS5cuNafUq3Tim+Irueuaa9WqlR544AE98MAD2rp1qzp37qwpU6Y4vA27vjpy5Ii+/vprTZw4UU888YQZP/n7oy41b95cmzZtkmEYDn1WXZ+64uTv8NM5JzX9Di1YsEAlJSWaP3++w50A7nr5G4CzA890A8Ap+Oabb/T0008rKSlJQ4YMqbHc4cOHq8Q6d+4sSeaUT5Xz5bprLui3337b4RnFDz/8UJmZmeYbgaXjycLq1asdpoj67LPPqkwtdjptGzBggCoqKvTKK684xKdNmyaLxeKw/9oYMGCAsrKy9MEHH5ix8vJyvfzyywoLC1PPnj1Pe5tbt25VRkZGlfjRo0e1atUqRUdHKyYmRv7+/ho8eLD+85//VJu45uTknPa+pePnubpbV2+44Qbt27dP//znP6usKyoqUmFh4Wntx8/PT9dee60WLFigNWvWVFlfOcp4ww03aNWqVVq4cGGVMkePHlV5eflp7fdkKSkpioiI0DPPPKOysrIq6105jykpKSorK3M4V3a73Zwe7ES1veaOHTum4uJih1irVq0UHh5eZSq3+qpypPnkkWV3vJneXVJSUrRv3z7Nnz/fjBUXF1d7PZyu6r7DT+ec1PQ7VN02cnNzNWvWrFq3GcDZg5FuADjJl19+qd9++03l5eXKzs7WN998o8WLF6t58+aaP3++goKCaqz71FNP6dtvv9XAgQPVvHlzHThwQK+++qqaNm1qzpXbqlUrRUVFaebMmQoPD1doaKi6d+9e7TOYp6JBgwa65JJLNHLkSGVnZ2v69Olq3bq1w8uHbr/9dn344Yfq37+/brjhBm3fvl3vvPOOw4ucTrdtqampuvzyy/XYY49p165dOv/887Vo0SJ9+umnGjNmTJVtu+rOO+/UP/7xD40YMUJr165VixYt9OGHH2rlypWaPn16lWfKT8XPP/+sW265RVdeeaUuvfRSNWjQQPv27dNbb72l/fv3a/r06eY/pp999lktXbpU3bt31x133KEOHTro8OHDWrdunZYsWVLtH1r+SLdu3fTB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/eMf/1DPnj0VGBioiRMnmnWSkpK0atUqzZ07VzfccMMJpyBar7zyivz9/dWuXTsNHDhQX3/9te644w5JUqNGjdSqVSuXjuVkr776qh5++GEVFhaqbdu2Wrx4saxW6ynVLS4u1iOPPKKbb75ZERERZvwvf/mLunbtqgYNGui7777T+PHjlZmZqalTp7qlze5C0g3AJ0QFRem6DtcpKijqhGCUdN11xz8BAMDZ6x//kE5IQiVJQ4ZI77wj7d0rdetWtY5hHP8cMUJavdpx3b//LQ0dKs2dK40e7biuXz9p4UKXmhkTE6OBAwdq9uzZMgxDAwcOVKNGjRzKbNu2TceOHdMVV1zhEC8tLXW4DX3GjBl68803lZGRoaKiIpWWlqpz584OdTp27Ch/f39zuXHjxlq/fr25PHr0aI0++fhcNGTIEF1xxRXKzMzUCy+8oBtuuEErV65UUFCQ03plZWW64YYbZBiGXnvtNYd148aNM/+7U6dOslqtuuuuuzRp0iTZbDa3tNsdSLoB+ISW0S017/p5JwVbSvPmVV8BAACcPe66q+o0odHRxz+bNpXWrq257uzZ1Y90S9INN0j/G202hYfXpqW67bbbzER3xowZVdYXFBRIkj7//HM1adLEYV1lovn+++/rwQcf1JQpU5ScnKzw8HA9//zz+v777x3KBwYGOixbLBbZ7fZatb8mkZGRioyMVJs2bdSjRw9FR0fr448/1s0331xjncqEe/fu3frmm28cRrmr0717d5WXl2vXrl1q27atuw/BZSTdAHxCaUWpDhQeUGxorKz+/7uVqbRUOnBAio2VTvH2JgAA4IUaNz7+U52goN9vJa+Os+QtJub4jxv1799fpaWlslgsSklJqbK+Q4cOstlsysjIUM+ePavdxsqVK3XRRRfp3nvvNWPbt293aztrwzAMGYahkpKSGstUJtxbt27V0qVL1bBhwz/cbnp6uvz8/BQbG+vO5tYaL1ID4BM2HNigxGmJ2nBgwwnBDVJi4vFPAACAesDf31+//vqrNm3a5HDrd6Xw8HA9+OCDGjt2rN566y1t375d69at08svv6y33npLktSmTRutWbNGCxcu1JYtW/T444/rxx9/PO22vPLKK+rTp4/TMocPH1Z6ero2/e+5+M2bNys9PV1ZWVmSpB07dmjSpEnmm8e/++47XX/99QoODtaAAQPM7bRr104ff/yxpOMJ93XXXac1a9bo3XffVUVFhbKyspSVlaXS0lJJ0qpVqzR9+nT9/PPP2rFjh959913zhXLRlXcx1BOMdAMAAABAPfJHt1E//fTTiomJ0aRJk7Rjxw5FRUWpa9euevTRRyVJd911l3766SfdeOONslgsuvnmm3Xvvffqyy+/PK12HDx48A9HyOfPn6/bbrvNXL7pppskSU8++aQmTJigoKAg/fe//9X06dN15MgRxcXF6bLLLtN3333nMCK9efNm5ebmSpL27dun+fPnS1KV59CXLl2qXr16yWaz6f3339eECRNUUlKipKQkjR071uE57/rCYhiVbwhATfLy8hQZGanc3Nw/vADORna7XQcOHFBsbKz8/Lg5wpvUtu9SU2u3/wULalffndZlrlO317tp7Z1r1bXx/24hW7fu+ItT1q51fltZHeC68270n/ei77wXfee93Nl3xcXF2rlzp5KSkv7wBV1wD8MwVF5eroCAAFkslrpujts5+5061TyRbyQAAAAAADyEpBsAAAAAAA/hmW4APqFzfGcVP1asQP8Tpsbo3FkqLpZOmi4DAAAAcBeSbgA+wc/iJ1uA7aSgn2SzVV8BAAAAcANuLwfgE7Yc2qJes3tpy6EtJwS3SL16Hf8EAAAAPICkG4BPKCgt0PLdy1VQWnBCsEBavvz4JwAAAOABJN0AAAAAAHgISTcAAAAAAB5C0g0AAAAAgIeQdAPwCc0im+mfqf9Us8hmJwSbSf/85/FPAACAs9iyZctksVh09OhRSdLs2bMVFRVVp23yFSTdAHxCo5BGur3r7WoU0uiEYCPp9tuPfwIAANSRESNGyGKx6O67766yLi0tTRaLRSNGjHDrPm+88UZtqaMZXP7+97/roosuUkhISLWJ/6FDh9S/f38lJCTIZrMpMTFRo0ePVl5entPtHj58WEOGDFFERISioqI0atQoFZz0wtxffvlFl156qYKCgpSYmKjJkye789CqRdINwCccPHZQb6x7QwePHTwheFB6443jnwAAAHUoMTFR77//voqKisxYcXGx5syZo2YeuCsvODhYsbGxbt/uqSgtLdX111+ve+65p9r1fn5+uuaaazR//nxt2bJFs2fP1pIlS6r9o8SJhgwZoo0bN2rx4sX67LPP9O233+rOO+801+fl5alfv35q3ry51q5dq+eff14T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fvB6M9Yif73eXRyrFvnrndQEAAAAXFenSffy5cuVlpam1atXa/HixSorK1O/fv1UWFholhk7dqwWLFigefPmafny5dq/f78GDRpkrq+oqNDAgQNVWlqq7777Tm+99ZZmz56tJ554wiyzc+dODRw4UJdffrnS09M1ZswY3X777Vq4cOEZPV4AAAAAgG+p02e6v/rqK4fl2bNnKzY2VmvXrtVll12m3Nxc/etf/9KcOXPUu3dvSdKsWbPUvn17rV69Wj169NCiRYu0adMmLVmyRHFxcercubOefvppPfLII5owYYKsVqtmzpyppKQkTZkyRZLUvn17rVixQtOmTVNKSsoZP24AAAAAgG+oV8905+bmSpIaNGggSVq7dq3KysrUt29fs0y7du3UrFkzrVq1SpK0atUqnXfeeYqLizPLpKSkKC8vTxs3bjTLnLiNyjKV2wAAAAAAwBPqzdvL7Xa7xowZo4svvljnnnuuJCkrK0tWq1VRUVEOZePi4pSVlWWWOTHhrlxfuc5Zmby8PBUVFSk4ONhhXUlJiUpKSszlvLw8s412u72WR+p97Ha7DMPwyWN3lcVS+23U9nRbLJLFYpfFYshi8d6+c8d5+N+WzM/fz0d1sfrh5L7j8vMufG96L/rOe9F33ou+826+3H+nesz1JulOS0vThg0btGLFirpuiiZNmqSJEydWiefk5Ki4uLgOWlS37Ha7cnNzZRiG/Pzq1c0R9VZiYu23ceCAO9pgV6NGx/uunt3Ycsrccx6kJmqstjlbFNAoRH46vtHyJo31QNstKg8IUaJfLXfkdo59V9vzgDOL703vRd95L/rOe9F33s2X+y8/P/+UytWLpHv06NH67LPP9O2336pp06ZmPD4+XqWlpTp69KjDaHd2drbi4+PNMj/88IPD9irfbn5imZPfeJ6dna2IiIgqo9ySNH78eI0bN85czsvLU2JiomJiYhQREVG7g/VCdrtdFotFMTExPnchuWrPntpvIza29m04Plpq0d69MTIM7+w7d5wHb3Ry39X2PODM4nvTe9F33ou+8170nXfz5f4LCgo6pXJ1mnQbhqH77rtPH3/8sZYtW6akpCSH9d26dVNgYKC+/vprDR48WJK0efNmZWRkKDk5WZKUnJysv//97zpw4IBi//ev0sWLFysiIkIdOnQwy3zxxRcO2168eLG5jZPZbDbZ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ffddlZaW6s0335TValXHjh2Vnp6uqVOnknQDAAAAADzqtJLuNm3aKDMzU0uXLpUk3XjjjXrppZcUFxfnkcZJ0rJlyxQbG6vo6Gj17t1bf/vb39SwYUNJ0qpVqxQVFWUm3JLUt29f+fn56fvvv9ef//xnrVq1SpdddpmsVqtZJiUlRc8995yOHDmi6OjoKvssKSlRSUmJuZyXlydJstvtstvtnjrUestut8swDJ869tP425HH1PZ0WyySxWKXxWLIYvHevnPHefjflszP389HdbH64eS+c995cI0PXf5u4Yvfm2cL+s570Xfei77zbr7cf6d6zKeVdBuG4bD85ZdfqrCw8HQ2cVr69++vQYMGKSkpSdu3b9ejjz6qK6+8UqtWrZK/v7+ysrIUGxvrUCcgIEANGjRQVtbxFyNlZWUpKSnJoUzlHwmysrKqTbonTZqkiRMnVonn5OSouLjYXYfnNex2u3Jzc2UYhvz8XHoNgNdJTKzrFkgHDtSu/vFjsKtRo9z/Xbve2XfuOQ9ShF+FWhVfpWaxFYq0H99oRESF1rW6ShHNKpQYWcsduZ1j37nrPLiqtvv3Nb74vXm2oO+8F33nveg77+bL/Zefn39K5Vx6prvSyUm4u910003mf5933nnq1KmTWrVqpWXLlqlPnz4e2+/48eM1btw4czkvL0+JiYmKiYlRRESEx/ZbX9ntdlksFsXExPjMhbRnT123QDrp70mnbc+eytFSi/bujZFheGffueM8/G9L6qBPlScpr3KdYpXe4VM5BOuJk/vOfefBNbXdv6/xxe/NswV9573oO+9F33k3X+6/oKCgUyp3Wkl35RvET46dKS1btlSjRo20bds29enTR/Hx8Tpw0vBLeXm5Dh8+bD4HHh8fr+zsbIcylcs1PStus9mqvLBNkvz8/HzuF6mSxWLxqeP38N+TTkltT3XlMRiGRYbh57VJt7vOg91SqpKAA7KVx8rPOP64SYC9VJElB5Rri1W5n9XJVurGiX3nrvPgKh+59N3K1743zyb0nfei77wXfefdfLX/TvV4T/v28hEjRpgJaXFxse6+++4qby//6KOPTmezp2zv3r06dOiQGjduLElKTk7W0aNHtXbtWnXr1k2S9M0338hut6t79+5mmccee0xlZWUKDAyUJC1evFht27at9tZyAGen/OAN+m+Hbrp001pFHjv+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",
            "text/plain": [
              "<Figure size 1000x600 with 1 Axes>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "# Read the training source file and analyze sentence lengths\n",
        "with open(\"wmt16/train_trg.bpe\", \"r\", encoding=\"utf8\") as file:\n",
        "    lines = file.readlines()\n",
        "\n",
        "# Split each line and calculate lengths\n",
        "lengths = [len(line.strip().split()) for line in lines]\n",
        "\n",
        "# Create a histogram of sentence lengths\n",
        "plt.figure(figsize=(10, 6))\n",
        "plt.hist(lengths, bins=50, alpha=0.7, color='blue')\n",
        "plt.xlabel('Sentence Length (number of tokens)')\n",
        "plt.ylabel('Frequency')\n",
        "plt.title('Distribution of Sentence Lengths in Training Data')\n",
        "plt.grid(True, alpha=0.3)\n",
        "\n",
        "# Add some statistics as text\n",
        "plt.axvline(np.mean(lengths), color='r', linestyle='dashed', linewidth=1, label=f'Mean: {np.mean(lengths):.2f}')\n",
        "plt.axvline(np.median(lengths), color='g', linestyle='dashed', linewidth=1, label=f'Median: {np.median(lengths):.2f}')\n",
        "plt.legend()\n",
        "\n",
        "# Display some statistics\n",
        "print(f\"Total sentences: {len(lengths)}\")\n",
        "print(f\"Min length: {min(lengths)}\")\n",
        "print(f\"Max length: {max(lengths)}\")\n",
        "print(f\"Mean length: {np.mean(lengths):.2f}\")\n",
        "print(f\"Median length: {np.median(lengths)}\")\n",
        "\n",
        "plt.tight_layout()\n",
        "plt.show()\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 12,
      "id": "bbd86f3e4db77521",
      "metadata": {
        "ExecuteTime": {
          "end_time": "2025-07-11T08:05:12.693773Z",
          "start_time": "2025-07-11T08:05:12.554874Z"
        },
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 702
        },
        "id": "bbd86f3e4db77521",
        "outputId": "7c91f47d-9a75-45c7-b9ac-5e4a66e22f01"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Total sentences: 29000\n",
            "Min length: 16\n",
            "Max length: 215\n",
            "Mean length: 63.07\n",
            "Median length: 60.0\n"
          ]
        },
        {
          "data": {
            "image/png": "iVBORw0KGgoAAAANSUhEUgAAA94AAAJOCAYAAABBfN/cAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjAsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvlHJYcgAAAAlwSFlzAAAPYQAAD2EBqD+naQAAkEBJREFUeJzs3Xd8FHX+x/H3bpJNL5RUCCEUadJVREFQkIAYC9hBiigW8BRsh56K5URREAsn56lgV/BsiIp0pNhABEHpEEoSairpO78/+GXPJYFMQoZM4PV8PPIIO/Oeme/ON7Pkk+8Uh2EYhgAAAAAAgCWcNd0AAAAAAABOZxTeAAAAAABYiMIbAAAAAAALUXgDAAAAAGAhCm8AAAAAACxE4Q0AAAAAgIUovAEAAAAAsBCFNwAAAAAAFqLwBgAAAADAQhTeAHASxo8fL4fDcUq21bNnT/Xs2dPzevHixXI4HPrkk09OyfaHDRumxo0bn5JtVVVOTo5uvfVWxcTEyOFw6N57763pJsHGduzYIYfDoRdeeMGybZzKz4jqMmPGDDkcDu3YsaPSy5Z+Li1evLja2wUAtRmFNwD8v9JfNku/AgICFBcXp6SkJL388svKzs6ulu3s3btX48eP15o1a6plfdXJzm0z45lnntGMGTN055136t1339XNN9983GxhYaFeeukldezYUWFhYYqIiFCbNm00cuRI/fnnn5a284MPPtCUKVMs3cap1LNnT5199tk13Yzj+vrrrzV+/PiabsZJ69mzp9dn1PG+Tof3WhVWfoavWLFC48ePV0ZGRvU1GMAZxWEYhlHTjQAAO5gxY4aGDx+uJ598UomJiSoqKlJaWpoWL16sefPmqVGjRvryyy/Vrl07zzLFxcUqLi5WQECA6e388ssvOvfcczV9+nQNGzbM9HKFhYWSJJfLJenoyNLFF1+sWbNm6ZprrjG9nqq2raioSG63W/7+/tWyLSucf/758vX11bJlyyrMJicn65tvvtGNN96orl27qqioSH/++ae++uorPfXUU5Xqm8q6/PLL9fvvv1dpRNGOevbsqQMHDuj333+v6aaUa/To0Zo6daqO/ZVnx44dSkxM1PPPP6/777/fkm1X5TPieObNm6f09HTP659//lkvv/yyHn74YbVq1cozvV27dl6fU5VVUlKioqIi+fv7V3q03u12q7CwUC6XS07nqR3fqcpnuFkvvPCCHnjgAW3fvt32Z/4AsCffmm4AANhNv379dM4553hejxs3TgsXLtTll1+uK664Qn/88YcCAwMlSb6+vvL1tfaj9MiRIwoKCvIU3DXFz8+vRrdvxr59+9S6desKcz///LO++uor/fOf/9TDDz/sNe/VV19lVAvVpjo/Iy699FKv1wEBAXr55Zd16aWXel2Gcqzc3FwFBweb3o6Pj498fHyq1Ean01ktf2Q4GZX5DAeAU4VTzQHAhEsuuUSPPvqodu7cqffee88zvbzrN+fNm6du3bopIiJCISEhatGihae4W7x4sc4991xJ0vDhwz2nRM6YMUPS/07ZXbVqlS666CIFBQV5lj32Gu9SJSUlevjhhxUTE6Pg4GBdccUV2rVrl1emcePG5Y7g/nWdFbWtvGu8c3Nzdd999yk+Pl7+/v5q0aKFXnjhhTIjiw6HQ6NHj9bnn3+us88+W/7+/mrTpo2+/fbb8nf4Mfbt26cRI0YoOjpaAQEBat++vd5++23P/NLrSrdv3645c+Z42n68EeWtW7dKki688MIy83x8fFSvXj2vaXv27NEtt9yi6OhoT9vfeustr0xpG2bOnKl//vOfatiwoQICAtSrVy9t2bLFk+vZs6fmzJmjnTt3etr51/1aUFCgxx9/XM2aNZO/v7/i4+P14IMPqqCgoMr7dM+ePRoxYoTi4uLk7++vxMRE3XnnnZ6zKCQpIyND9957r6cvmzVrpueee05ut7vcfVgV33zzjbp3767g4GCFhoaqf//+Wr9+vVdm2LBhCgkJ0Z49e3TVVVcpJCREkZGRuv/++1VSUuKVPXjwoG6++WbPpQJDhw7Vb7/9VubndurUqZ59Vvp1rNdff11NmzaVv7+/zj33XP38889e89PS0jR8+HA1bNhQ/v7+io2N1ZVXXlnhWQvlfUac7PFgZnsbNmzQTTfdpDp16qhbt26SpLVr12rYsGFq0qSJAgICFBMTo1tuuUUHDx70Wkd513g3btxYl19+uZYtW6bzzjtPAQEBatKkid555x2vZcu7xrv0c23Dhg26+OKLFRQUpAYNGmjixIll2r9z505dccUVCg4OVlRUlMaMGaO5c+ee9HXjx/sMN7NPxo8frwceeECSlJiYWObzZfr06brkkksUFRUlf39/tW7dWq+99lqV2wrg9MSINwCYdPPNN+vhhx/Wd999p9tuu63czPr163X55ZerXbt2evLJJ+Xv768tW7Zo+fLlkqRWrVrpySef1GOPPaaRI0eqe/fukqQLLrjAs46DBw+qX79+uuGGGzR48GBFR0efsF3//Oc/5XA49NBDD2nfvn2aMmWKevfurTVr1lRqVMdM2/7KMAxdccUVWrRokUaMGKEOHTpo7ty5euCBB7Rnzx69+OKLXvlly5bp008/1V133aXQ0FC9/PLLGjhwoFJSUsoUun+Vl5ennj17asuWLRo9erQSExM1a9YsDRs2TBkZGbrnnnvUqlUrvfvuuxozZowaNmyo++67T5IUGRlZ7joTEhIkSe+//74uvPDCE45Ipqen6/zzz/cUS5GRkfrmm280YsQIZWVllbmB27PPPiun06n7779fmZmZmjhxogYNGqQff/xRkvTII48oMzNTu3fv9uyjkJAQSUdP073iiiu0bNkyjRw5Uq1atdK6dev04osvatOmTfr8888rvU/37t2r8847TxkZGRo5cqRatmypPXv26JNPPtGRI0fkcrl05MgR9ejRQ3v27NHtt9+uRo0aacWKFRo3bpxSU1Or5Xr0d999V0OHDlVSUpKee+45HTlyRK+99pq6deumX3/91euPDyUlJUpKSlKXLl30wgsvaP78+Zo0aZKaNm2qO++807OvkpOT9dNPP+nOO+9Uy5Yt9cUXX2jo0KFe27399tu1d+9ezZs3T++++265bfvggw+UnZ2t22+/XQ6HQxMnTtSAAQO0bds2z5keAwcO1Pr163X33XercePG2rdvn+bNm6eUlJQqnXpc1ePBrGuvvVbNmzfXM8884/lD2Lx587Rt2zYNHz5cMTExWr9+vV5//XWtX79eP/zwQ4WnlW/ZskXXXHONRowYoaFDh+qtt97SsGHD1LlzZ7Vp0+aEyx4+fFh9+/bVgAEDdN111+mTTz7RQw89pLZt26pfv36Sjv4h75JLLlFqaqruuecexcTE6IMPPtCiRYtOen9I5X+Gm9knAwYM0KZNm/Thhx/qxRdfVP369SX97/PltddeU5s2bXTFFVfI19dXs2fP1l133SW3261Ro0ZVS9sBnAYMAIBhGIYxffp0Q5Lx888/HzcTHh5udOzY0fP68ccfN/76Ufriiy8akoz9+/cfdx0///yzIcmYPn16mXk9evQwJBnTpk0rd16PHj08rxctWmRIMho0aGBkZWV5ps+cOdOQZLz00kueaQkJCcbQoUMrXOeJ2jZ06FAjISHB8/rzzz83JBlPP/20V+6aa64xHA6HsWXLFs80SYbL5fKa9ttvvxmSjFdeeaXMtv5qypQphiTjvffe80wrLCw0unbtaoSEhHi994SEBKN///4nXJ9hGIbb7fbs6+joaOPGG280pk6dauzcubNMdsSIEUZsbKxx4MABr+k33HCDER4ebhw5csQwjP/1R6tWrYyCggJP7qWXXjIkGevWrfNM69+/v9e+LPXuu+8aTqfT+P77772mT5s2zZBkLF++3DPN7D4dMmSI4XQ6y/25drvdhmEYxlNPPWUEBwcbmzZt8pr/97//3fDx8TFSUlLKLPtXPXr0MNq0aXPc+dnZ2UZERIRx2223eU1PS0szwsPDvaYPHTrUkGQ8+eSTXtmOHTsanTt39rz+73//a0gypkyZ4plWUlJiXHLJJWV+hkeNGmWU9yvP9u3bDUlGvXr1jEOHDnmmf/HFF4YkY/bs2YZhGMbhw4cNScbzzz9/wv1QnmM/Iwzj5I6Hv5o1a5YhyVi0aFGZ7d14441l8qU/q3/14YcfGpKMpUuXeqaVfhZu377dMy0hIaFMbt++fYa/v79x3333eaaVHgd/bVPpsfbOO+94phUUFBgxMTHGwIEDPdMmTZpkSDI+//xzz7S8vDyjZcuWZdZZnqp8hpvdJ88//3yZfXKidSQlJRlNmjQ5YXsBnFk41RwAKiEkJOSEd8aNiIiQJH3xxRdVPkXX399fw4cPN50fMmSIQkNDPa+vueYaxcbG6uuvv67S9s36+uuv5ePjo7/97W9e0++77z4ZhqFvvvnGa3rv3r3VtGlTz+t27dopLCxM27Ztq3A7MTExuvHGGz3T/Pz89Le//U05OTlasmRJpdvucDg0d+5cPf3006pTp44+/PBDjRo1SgkJCbr++us913gbhqH//ve/Sk5OlmEYOnDggOcrKSlJmZmZWr16tde6hw8f7nU9fumZAxW9T0maNWuWWrVqpZYtW3pt65JLLpGkMiN/Fe1Tt9utzz//XMnJyV7XvP51P5Rut3v37qpTp47Xdnv37q2SkhItXbq0wrafyLx585SRkaEbb7zRa/0+Pj7q0qVLuSOad9xxh9fr7t27e+3Db7/9Vn5+fl5nnzidziqNMF5//fWqU6eO17ak//VZYGCgXC6XFi9erMOHD1d6/eWp6vFg1rH7T5LXGTD5+fk6cOCAzj//fEkq83NcntatW3v2jXR0xLdFixam2hwSEqLBgwd7XrtcLp133nll+rRBgwa64oorPNMCAgKOe4ZRVRz7GX6y++TYdWRmZurAgQPq0aOHtm3bpszMzGpqOYDajlPNAaAScnJyFBUVddz5119/vd544w3deuut+vvf/65evXppwIABuuaaa0zf4bdBgwaVupFa8+bNvV47HA41a9bM8jtm79y5U3FxcV5FvyTP3ZV37tzpNb1Ro0Zl1lGnTp0KC5mdO3eqefPmZfbf8bZjlr+/vx555BE98sgjSk1N1ZIlS/TSSy9p5syZ8vPz03vvvaf9+/crIyNDr7/+ul5//fVy17Nv3z6v18e+z9KCzkzBtnnzZv3xxx/HPUW+om2Vbq90W/v371dWVlaFj/ravHmz1q5da3q7lbV582ZJ8vwB4VhhYWFerwMCAsq05diflZ07dyo2NlZBQUFeuWbNmlW6fRX1mb+/v5577jndd999io6O1vnnn6/LL79cQ4YMUUxMTKW3V942S7dbXYV9YmJimWmHDh3SE088oY8++qhMn5opEE+mzQ0bNixzKnudOnW0du1az+udO3eqadOmZXJV6dPjOfYz/GT3iSQtX75cjz/+uFauXKkjR46UWUd4ePjJNxxArUfhDQAm7d69W5mZmSf8JTAwMFBLly7VokWLNGfOHH377bf6+OOPdckll+i7774zdadgK+62e7xrN0tKSqp89+LKOt52DBs81TI2NlY33HCDBg4cqDZt2mjmzJmaMWOG56yFwYMHl7l2uNSxjyY6mffpdrvVtm1bTZ48udz58fHx1batY7d76aWX6sEHHyx3/llnnVWp9ZW3funodd7lFarHXmN/qn4mK9reX/fjvffeq+TkZH3++eeaO3euHn30UU2YMEELFy5Ux44dLdnmySjvc+S6667TihUr9MADD6hDhw4KCQmR2+1W3759TZ2hczJttsPxX95n+Mnuk61bt6pXr15q2bKlJk+erPj4eLlcLn399dd68cUXq/XmhABqNwpvADCp9MZMSUlJJ8w5nU716tVLvXr10uTJk/XMM8/okUce0aJFi9S7d+9KPxe3IqWjiaUMw9CWLVu8CsI6deqU+4isnTt3qkmTJp7XlWlbQkKC5s+fr+zsbK9R7z///NMzvzokJCRo7dq1crvdXqPe1b0d6egp7O3atdPmzZt14MABRUZGKjQ0VCUlJerdu3e1bed4+7lp06b67bff1KtXr2r5OYmMjFRYWFiFz9du2rSpcnJyqvU9Hrt+SYqKiqq2bSQkJGjRokWex+2V+usd5EtV1zHXtGlT3Xfffbrvvvu0efNmdejQQZMmTfK6S7ZdHT58WAsWLNATTzyhxx57zDP92M+PmpSQkKANGzbIMAyvPiuvT6vi2M/wyuyT4/0MzZ49WwUFBfryyy+9zgiorhvCATh9cI03AJiwcOFCPfXUU0pMTNSgQYOOmzt06FCZaR06dJAkz+OgSp+nW13Pin7nnXe8rln85JNPlJqa6rlTsHS0YPjhhx+8Hh/11VdflXnsWGXadtlll6mkpESvvvqq1/QXX3xRDofDa/sn47LLLlNaWpo+/vhjz7Ti4mK98sorCgkJUY8ePSq9zs2bNyslJaXM9IyMDK1cuVJ16tRRZGSkfHx8NHDgQP33v/8tt3jdv39/pbctHd3P5Z3Get1112nPnj36z3/+U2ZeXl6ecnNzK7Udp9Opq666SrNnz9Yvv/xSZn7paON1112nlStXau7cuWUyGRkZKi4urtR2j5WUlKSwsDA988wzKioqKjO/KvsxKSlJRUVFXvvK7XZ7Hh32Vyd7zB05ckT5+fle05o2barQ0NAyj3mzq9IR52NHmKvjjvXVJSkpSXv27NGXX37pmZafn1/u8VBZ5X2GV2afHO9nqLx1ZGZmavr06SfdZgCnF0a8AeAY33zzjf78808VFxcrPT1dCxcu1Lx585SQkKAvv/xSAQEBx132ySef1NKlS9W/f38lJCRo3759+te//qWGDRt6nqXbtGlTRUREaNq0aQoNDVVwcLC6dOlS7jWZZtStW1fdunXT8OHDlZ6erilTpqhZs2ZeNyS69dZb9cknn6hv37667rrrtHXrVr333nteN3eqbNuSk5N18cUX65FHHtGOHTvUvn17fffdd/riiy907733lll3VY0cOVL//ve/NWzYMK1atUqNGzfWJ598ouXLl2vKlCllrjE347ffftNNN92kfv36qXv37qpbt6727Nmjt99+W3v37tWUKVM8v1A/++yzWrRokbp06aLbbrtNrVu31qFDh7R69WrNnz+/3D+2VKRz5876+OOPNXbsWJ177rkKCQlRcnKybr75Zs2cOVN33HGHFi1apAsvvFAlJSX6888/NXPmTM2dO7fcm6SdyDPPPKPvvvtOPXr08DyiLDU1VbNmzdKyZcsUERGhBx54QF9++aUuv/xyz+OhcnNztW7dOn3yySfasWOH5xFKx7N//349/fTTZaaXFjqvvfaabr75ZnXq1Ek33HCDIiMjlZKSojlz5ujCCy8s8wecilx11VU677zzdN9992nLli1q2bKlvvzyS09//HWEsnPnzpKkv/3tb0pKSpKPj49uuOEG09vatGmTevXqpeuuu06tW7eWr6+vPvvsM6Wnp1dqPTUpLCxMF110kSZOnKiioiI1aNBA3333nbZv317TTfO4/fbb9eqrr+rGG2/UPffco9jYWL3//vuez1yzZy6Y/QyvzD4p/Rl65JFHdMMNN8jPz0/Jycnq06ePXC6XkpOTdfvttysnJ0f/+c9/FBUVpdTU1GraMwBOC6f+RuoAYE+lj6Ip/XK5XEZMTIxx6aWXGi+99JLXY6tKHfuooAULFhhXXnmlERcXZ7hcLiMuLs648cYbyzym6YsvvjBat25t+Pr6ej366ESPZTre48Q+/PBDY9y4cUZUVJQRGBho9O/fv9zHYk2aNMlo0KCB4e/vb1x44YXGL7/8UmadJ2rbsY8TM4yjj4kaM2aMERcXZ/j5+RnNmzc3nn/+ec9jqkpJMkaNGlWmTcd7zNmx0tPTjeHDhxv169c3XC6X0bZt23IfeWb2cWLp6enGs88+a/To0cOIjY01fH19jTp16hiXXHKJ8cknn5SbHzVqlBEfH2/4+fkZMTExRq9evYzXX3/dkyntj1mzZnktW/rIqr+2Nycnx7jpppuMiIgIQ5LXfi0sLDSee+45o02bNoa/v79Rp04do3PnzsYTTzxhZGZmenKV2ac7d+40hgwZYkRGRhr+/v5GkyZNjFGjRnk99iw7O9sYN26c0axZM8Plchn169c3LrjgAuOFF14wCgsLT7g/Sx8XVd5Xr169vPZRUlKSER4ebgQEBBhNmzY1hg0bZvzyyy+ezNChQ43g4OAy2yjvsVz79+83brrpJiM0NNQIDw83hg0bZixfvtyQZHz00UeeXHFxsXH33XcbkZGRhsPh8KyntG/Ke0yYJOPxxx83DMMwDhw4YIwaNcpo2bKlERwcbISHhxtdunQxZs6cecL9crx2n+zxUOpEjxMr75GGu3fvNq6++mojIiLCCA8PN6699lpj7969Xu/VMI7/OLHyjq3jfS4d+zix8j7XyvtM2bZtm9G/f38jMDDQiIyMNO677z7Po+N++OGHE+6PqnyGm90nhnH0sXsNGjQwnE6n1/758ssvjXbt2hkBAQFG48aNjeeee8546623jvv4MQBnJodh2OCuNgAAANXg888/19VXX61ly5bpwgsvrOnmoBpMmTJFY8aM0e7du9WgQYOabg4AVAmFNwAAqJXy8vK87t5dUlKiPn366JdfflFaWpolTwiAtY7t0/z8fHXs2FElJSXatGlTDbYMAE4O13gDAIBa6e6771ZeXp66du2qgoICffrpp1qxYoWeeeYZiu5aasCAAWrUqJE6dOigzMxMvffee/rzzz/1/vvv13TTAOCkMOINAABqpQ8++ECTJk3Sli1blJ+fr2bNmunOO+/U6NGja7ppqKIpU6bojTfe0I4dO1RSUqLWrVvrwQcf1PXXX1/TTQOAk0LhDQAAAACAhXiONwAAAAAAFqLwBgAAAADAQtxczQS32629e/cqNDRUDoejppsDAAAAAKhhhmEoOztbcXFxcjpPPKZN4W3C3r17FR8fX9PNAAAAAADYzK5du9SwYcMTZii8TQgNDZV0dIeGhYXVcGtqF7fbrf379ysyMrLCvwLh1KotfbMmbY16TO+hJcOXqENMBxMLrJF69JCWLJE6mMjbVG3pnzMRfWNv9I990Tf2Rd/YG/1jX1lZWYqPj/fUiydC4W1C6enlYWFhFN6V5Ha7lZ+fr7CwMD4obKa29E1IbogUIIWEhpg7/kJC/ve9Fh+vtaV/zkT0jb3RP/ZF39gXfWNv9I/9mbkcmZ4DAAAAAMBCFN4AbM3pcCrUFSqnw+THldMphYYe/Q4AAADYAKeaA7C1DjEdlDUuqxILdJCyKpEHAAAALEbhDQAAAOC0U1JSoqKioppuxklzu90qKipSfn4+13ifYn5+fvLx8amWdVF4A7C1Dfs36NpZ12rWtbPUOrK1iQU2SNdeK82aJbU2kQcAAKcVwzCUlpamjIyMmm5KtTAMQ263W9nZ2aZu4oXqFRERoZiYmJPe9xTeAGwtvzhfG/ZvUH5xvskF8o8W3/km8wAA4LRSWnRHRUUpKCio1herhmGouLhYvr6+tf691CaGYejIkSPat2+fJCk2Nvak1kfhDQAAAOC0UFJS4im669WrV9PNqRYU3jUnMDBQkrRv3z5FRUWd1GnnXCQAAAAA4LRQek13UFBQDbcEp4vSn6WTvV8AhTcAAACA0wojw6gu1fWzROENwNaa1GmiL274Qk3qNDG5QBPpiy+OfgcAAABsgGu8AdhaRECErmhxRSUWiJCuqEQeAAAAsBgj3gBsLS0nTRO+n6C0nDSTC6RJEyYc/Q4AAFALDBs2TA6HQ3fccUeZeaNGjZLL5dLw4cNroGXm/PHHH7riiisUHh6u4OBgnXvuuUpJSfHMv/3229W0aVMFBgYqMjJSV155pf78888TrtMwDD322GOKjY1VYGCgevfurc2bN3vmL168WA6Ho9yvn3/+2bL3WlUU3gBsbW/2Xj288GHtzd5rcoG90sMPH/0OAABQS8THx+ujjz5SXl6eZ1p+fr4+/PBDNWrUqAZbdmJbt25Vt27d1LJlSy1evFhr167Vo48+qoCAAE+mc+fOmj59uv744w/NnTtXhmGoT58+KikpOe56J06cqJdfflnTpk3Tjz/+qODgYCUlJSn//x8Ze8EFFyg1NdXr69Zbb1ViYqLOOeccy993ZVF4AwAAAEAN69Spk+Lj4/Xpp596pn366adq1KiR2rdv75V1u92aMGGCEhMTFRgYqPbt2+uTTz7xzC8pKdGIESM881u0aKGXXnrJax3Dhg3TVVddpRdeeEGxsbGqV6+eRo0aVem7dz/yyCO67LLLNHHiRHXs2FFNmzbVFVdcoaioKE9m5MiRuuiii9S4cWN16tRJTz/9tHbt2qUdO3aUu07DMDRlyhT94x//0JVXXql27drpnXfe0d69e/X5559Lklwul2JiYjxf9erV0xdffKHhw4fb8uZ6FN4AAAAAYAO33HKLpk+f7nn91ltvadiwYWVyEyZM0DvvvKNp06Zp/fr1GjNmjAYPHqwlS5ZIOlqYN2zYULNmzdKGDRv02GOP6eGHH9bMmTO91rNo0SJt3bpVixYt0ttvv60ZM2ZoxowZnvnjx49X48aNj9tet9utOXPm6KyzzlJSUpKioqLUpUsXT3FcntzcXE2fPl2JiYmKj48vN7N9+3alpaWpd+/enmnh4eHq0qWLVq5cWe4yX375pQ4ePGjbU/K5uRoAAACA01tq6tGvv6pTR0pMlPLzpQ0byi7TqdPR7xs3Srm53vMaN5bq1pX275d27fKeFxoqNW9epWYOHjxY48aN086dOyVJy5cv14cffqhFixZ5MgUFBXrmmWc0f/58de3aVZLUpEkTLVu2TP/+97/Vo0cP+fn56YknnvAsk5iYqJUrV2rmzJm67rrr/rIL6ujVV1+Vj4+PWrZsqf79+2vBggW67bbbJEn169dX06ZNj9veffv2KScnR88++6yefvppPffcc/r22281YMAALVq0SD169PBk//Wvf+nBBx9Ubm6uWrRooXnz5snlcpW73rT/v1dPdHS01/To6GjPvGO9+eabSkpKUsOGDY/b3ppE4Q3A1iICInRN62sUERBhcoEI6Zprjn4HAACQpH//W/pLISpJGjRIeu89afduqXPnsssYxtHvw4ZJP/zgPe/dd6XBg6WZM6XRo73n9ekjzZ1bpWZGRkaqf//+mjFjhgzDUP/+/VW/fn2vzJYtW3TkyBFdeumlXtMLCwvVsWNHz+upU6fqrbfeUkpKivLy8lRYWKgOHTp4LdOmTRv5+Ph4XsfGxmrdunWe16NHj9boY9/fX7jdbknSlVdeqTFjxkiSOnTooBUrVmjatGlehfegQYN06aWXKjU1VS+88IKuu+46LV++3Ota8KravXu35s6dW2ZE304ovAHYWpM6TTTr2lmVWKCJNKsSeQAAcPq7/fayjxutU+fo94YNpVWrjr/sjBnlj3hL0nXXSf8/6uwRGnoyLdUtt9ziKXanTp1aZn5OTo4kac6cOWrQoIHXPH9/f0nSRx99pPvvv1+TJk1S165dFRoaqueff14//vijV97Pz8/rtcPh8BTTZtSvX1++vr5q3bq11/RWrVpp2bJlXtPCw8MVHh6u5s2b6/zzz1edOnX02Wef6cYbbyyz3piYGElSenq6YmNjPdPT09PL/PFAkqZPn6569erpChs/UpbCG4CtFZYUal/uPkUFR8nlU/7pSN4LFEr79klRUdJxTl8CAABnmNjYo1/lCQj432nl5WnR4vjzIiOPflWjvn37qrCwUA6HQ0lJSWXmt27dWv7+/kpJSfEaUf6r5cuX64ILLtBdd93lmbZ169Zqbad09AZn5557rjZu3Og1fdOmTUpISDjucoZhyDAMFRQUlDs/MTFRMTExWrBggafQzsrK0o8//qg777yzzLqmT5+uIUOGlPlDgp1wczUAtvb7vt8V/2K8ft/3u8kFfpfi449+BwAAqGV8fHz0xx9/aMOGDV6ngZcKDQ3V/fffrzFjxujtt9/W1q1btXr1ar3yyit6++23JUnNmzfXL7/8orlz52rTpk169NFHq/Rs61dffVW9evU6YeaBBx7Qxx9/rP/85z/asmWLXn31Vc2ePdtT9G/btk0TJkzQqlWrlJKSohUrVujaa69VYGCgLrvsMs96WrZsqc8++0zS0ZH3e++9V08//bS+/PJLrVu3TkOGDFFcXJyuuuoqr+0vXLhQ27dv16233lrp93cqMeINAAAAADYSFhZ2wvlPPfWUIiMjNWHCBG3btk0RERHq1KmTHn74YUnS7bffrl9//VXXX3+9HA6HbrzxRt1111365ptvKtWOAwcOVDhSfvXVV2vatGmaMGGC/va3v6lFixb673//q27dukmSAgIC9P3332vKlCk6fPiwoqOjddFFF2nFihVejxzbuHGjMjMzPa9Lb8Q2cuRIZWRkqFu3bvr222/LXBP+5ptv6oILLlDLli0r9d5ONYdhlN41AMeTlZWl8PBwZWZmVngQwJvb7da+ffsUFRUlp5MTLE6l5OQTz3c43IqP36ddu6JkGOX3zezZFjSsklanrlbn1ztr1chV6hR7gtPAPAusPnqDlFWrTnzamM1x7NgXfWNv9I990Tf2dTr1TX5+vrZv367ExMRquWmXHRiGoeLiYvn6+try+dSnuxP9TFWmTqzdRxYAAAAAADZH4Q0AAAAAgIW4xhuArXWI6aD8R/Ll52PyLpUdOkj5+ZKN72oJAACAMwuFNwBbczqc8vf1r8QCTsm/EnkAAADAYpxqDsDWNh3cpJ4zemrTwU0mF9gk9ex59DsAAABgA4x4Aziuiu6MXpHquCt6TmGOluxcopzCHJML5EhLlhz9DgAAANgAI94AAAAAAFiIwhsAAAAAAAtReAMAAAAAYCEKbwC21ii8kf6T/B81Cm9kcoFG0n/+c/Q7AAAAJEmLFy+Ww+FQRkaGJGnGjBmKiIio0TadSSi8Adha/aD6urXTraofVN/kAvWlW289+h0AAKAWGDZsmBwOh+64444y80aNGiWXy6Xhw4dX6zavv/56barBp8DMmTNHXbp0UWBgoOrUqaOrrrrKa35KSor69++voKAgRUVF6YEHHlBxcfEJ13no0CENGjRIYWFhioiI0IgRI5RzzA13165dq+7duysgIEDx8fGaOHFidb+1clF4A7C1A0cO6I3Vb+jAkQMmFzggvfHG0e8AAAC1RHx8vD766CPl5eV5puXn5+vDDz9UIwvO5AsMDFRUVFS1r9eM//73v7r55ps1fPhw/fbbb1q+fLluuukmz/ySkhL1799fhYWFWrFihd5++23NmDFDjz322AnXO2jQIK1fv17z5s3TV199paVLl2rkyJGe+VlZWerTp48SEhK0atUqPf/88xo/frxef/11y95rKQpvALaWkpmi22bfppTMFJMLpEi33Xb0OwAAQC3RqVMnxcfH69NPP/VM+/TTT9WoUSO1b9/eK+t2uzVhwgQlJiYqMDBQ7du31yeffOKV+frrr3XWWWcpMDBQF198sXbs2OE1/9hTzbdu3aorr7xS0dHRCgkJ0bnnnqv58+d7LdO4cWM988wzuuWWWxQaGqpGjRpVumgtLi7WPffco+eff1533HGHzjrrLLVu3VrXXXedJ/Pdd99pw4YNeu+999ShQwf169dPTz31lKZOnarCwsJy1/vHH3/o22+/1RtvvKEuXbqoW7dueuWVV/TRRx9p7969kqT3339fhYWFeuutt9SmTRvdcMMN+tvf/qbJkydX6j1UBYU3AAAAANjALbfcounTp3tev/XWWxo2bFiZ3IQJE/TOO+9o2rRpWr9+vcaMGaPBgwdryZIlkqRdu3ZpwIABSk5O1po1a3Trrbfq73//+wm3nZOTo8suu0wLFizQr7/+qr59+yo5OVkpxwxmTJo0Seecc45+/fVX3XXXXbrzzju1ceNGz/yePXuW2+ZSq1ev1p49e+R0OtWxY0fFxsaqX79++v333z2ZlStXqm3btoqOjvZMS0pKUlZWltavX1/ueleuXKmIiAidc845nmm9e/eW0+nUjz/+6MlcdNFFcrlcXuvduHGjDh8+fML9c7J8LV07AAAAANSw1OxUpeakek2rE1BHiXUSlV+crw37N5RZplNsJ0nSxgMblVuU6zWvcURj1Q2sq/25+7Ura5fXvFBXqJrXa16ldg4ePFjjxo3Tzp07JUnLly/Xhx9+qEWLFnkyBQUFeuaZZzR//nx17dpVktSkSRMtW7ZM//73v9WjRw+99tpratq0qSZNmiRJatGihdatW6fnnnvuuNtu376918j6U089pc8++0xffvmlRo8e7Zl+2WWX6a677pIkPfTQQ3rxxRe1aNEitWjRQpLUqFEjxcbGHnc727ZtkySNHz9ekydPVuPGjTVp0iT17NlTmzZtUt26dZWWluZVdEvyvE5LSyt3vWlpaWVOnff19fWsrzSTmJh43PXWqVPnuO0+WRTeAAAAAE5r/171bz2x5AmvaYPaDtJ7A97T7qzd6vx65zLLGI8bkqRhXwzTD7t/8Jr37tXvanC7wZq5fqZGfzPaa16fpn00d/DcKrUzMjJS/fv314wZM2QYhvr376/6x9wwdsuWLTpy5IguvfRSr+mFhYXq2LGjpKOnXXfp0sVrfmmRfjw5OTkaP3685syZo9TUVBUXFysvL6/MiHe7du08/3Y4HIqJidG+ffs80955550TbsftdkuSHnnkEQ0cOFCSNH36dDVs2FCzZs3S7bfffsLla6saLbwnTJigTz/9VH/++acCAwN1wQUX6LnnnvP8tUQ6eqpC6SkTpW6//XZNmzbN8zolJUV33nmnFi1apJCQEA0dOlQTJkyQr+//3t7ixYs1duxYrV+/XvHx8frHP/5xwlMgANhDiCtEPRJ6KMQVYnKBEKlHj6PfAQAAJN3e+XZd0eIKr2l1Ao6ObjYMa6hVI1cdd9kZV84od8Rbkq5rc526xnsXtKGu0JNq6y233OIZYZ46dWqZ+aV36Z4zZ44aNGjgNc/f37/K273//vs1b948vfDCC2rWrJkCAwN1zTXXlLmm2s/Pz+u1w+HwFNNmlI6Gt27d2qvdTZo08RT5MTEx+umnn7yWS09P98wrz7F/AJCOXk9+6NAhzzIxMTGe9Zhdb3Wp0cJ7yZIlGjVqlM4991wVFxfr4YcfVp8+fbRhwwYFBwd7crfddpuefPJJz+ugoCDPv0vveBcTE6MVK1YoNTVVQ4YMkZ+fn5555hlJ0vbt29W/f3/dcccdev/997VgwQLdeuutio2NVVJS0ql7wwAq7ax6Z2nxsMWVWOAsaXEl8gAA4LQXGxqr2NDyT38O8A3wnFZenhb1Wxx3XmRwpCKDI0+6fX/Vt29fFRYWyuFwlFurtG7dWv7+/kpJSVGPHj3KXUerVq305Zdfek374Ycfys2WWr58uYYNG6arr75a0tEC/9gbslWHzp07y9/fXxs3blS3bt0kSUVFRdqxY4cSEhIkHR2d/+c//6l9+/Z5Th+fN2+ewsLCvAr2v+ratasyMjK0atUqde589AyGhQsXyu12e0b/u3btqkceeURFRUWePyDMmzdPLVq0sPQ0c6mGb6727bffatiwYWrTpo3at2+vGTNmKCUlRatWef/FKSgoSDExMZ6vsLAwzzwzd7ybNm2aEhMTNWnSJLVq1UqjR4/WNddcoxdffPGUvl8Alec23CooLpDbMPmXVLdbKig4+h0AAKCW8fHx0R9//KENGzbIx8enzPzQ0FDdf//9GjNmjN5++21t3bpVq1ev1iuvvKK3335bknTHHXdo8+bNeuCBB7Rx40Z98MEHmjFjxgm327x5c3366adas2aNfvvtN910002VGskuNWTIEI0bN+6488PCwnTHHXfo8ccf13fffaeNGzfqzjvvlCRde+21kqQ+ffqodevWuvnmm/Xbb79p7ty5+sc//qFRo0Z5RvV/+ukntWzZUnv27JF09I8Nffv21W233aaffvpJy5cv1+jRo3XDDTcoLi5OknTTTTfJ5XJpxIgRWr9+vT7++GO99NJLGjt2bKXfZ2XZ6hrvzMxMSVLdunW9pr///vt67733FBMTo+TkZD366KOeUe/j3fHuzjvv1Pr169WxY0etXLlSvXv39lpnUlKS7r333nLbUVBQoIKCAs/rrKwsSUevR6jKD9+ZzO12yzAM9lsNcDgqmu+Ww2HI4bCub6qj21enrta5b5yrn2/9+YR/jf7fAqvlPPdcuX/+WepkIm9THDv2Rd/YG/1jX/SNfZ1OfVP6Xkq/apvSNoeGhnq9Pnb+k08+qfr162vChAnatm2bIiIi1KlTJ40bN06GYSg+Pl6ffPKJxo4dq1deeUXnnXee/vnPf2rEiBFl9k/p90mTJmnEiBG64IILVL9+fT344IPKysoqsy/L27d/nZaSkiKn03nC/T9x4kT5+Pjo5ptvVl5enrp06aIFCxYoIiJChmHI6XRq9uzZuuuuu9S1a1cFBwdryJAheuKJJzzrzc3N1caNG1VYWOiZ9t577+nuu+9Wr1695HQ6NWDAAL388sue+WFhYZo7d65Gjx6tzp07q379+nr00Ud12223Hbe9pe+tvFqwMseMw7DJT6Tb7dYVV1yhjIwMLVu2zDP99ddfV0JCguLi4rR27Vo99NBDOu+88zzPtxs5cqR27typuXP/dwODI0eOKDg4WF9//bX69euns846S8OHD/f6y8vXX3+t/v3768iRIwoM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FqLwBgAAAADAQhTeAAAAAABYiMIbgK35loQrOiNZviXhpvK5vuH6MTpZub7m8gAAAIDVeJwYAFsLLmiqc7d8aTqfFtxUT59rPg8AAABYjRFvALbmdhSpwHe/3I4iU3kfd5HCCvbLx20uDwAAAFiNwhuArWUHrtO8DlHKDlxnKt84e53enxelxtnm8gAAAIDVKLwBAAAAALAQhTcAAAAAABai8AYAAAAAwEIU3gAAAAAAWIjHiQGwtbAj7ZW0OlO+7mBT+e1h7XVdUqYKfM3lAQAAAKtReAOwNYd85OcOM513O3yU52c+DwAAAFiNU80B2FqO/2b92DxJOf6bTeVjczbriR+TFJtjLg8AAABYjRFvALZW4pOt/eHfqcQn21Q+qCRbnfZ/p6ASc/lTITm58ss4HFJ8vLRrl2QY0uzZ1d8uAAAAnBqMeAMAAAAAYCEKbwAAAAAALEThDQAAAACAhSi8AdhaQGG8zt75qgIK403l9wfE67WzX9X+AHN5AAAAwGpVKry3bdtW3e0AgHL5F0eq8f5R8i+ONJXP8o/U141HKcvfXB4AAACwWpUK72bNmuniiy/We++9p/z8/OpuEwB4FPoc0u6676nQ55CpfEjhIfXc/Z5CCs3lAQAAAKtVqfBevXq12rVrp7FjxyomJka33367fvrpp+puGwAoz3+H1jS5WXn+O0zlo/N26L41Nys6z1weAAAAsFqVCu8OHTropZde0t69e/XWW28pNTVV3bp109lnn63Jkydr//791d1OAAAAAABqpZO6uZqvr68GDBigWbNm6bnnntOWLVt0//33Kz4+XkOGDFFqamp1tRMAAAAAgFrppArvX375RXfddZdiY2M1efJk3X///dq6davmzZunvXv36sorr6yudgIAAAAAUCtVqfCePHmy2rZtqwsuuEB79+7VO++8o507d+rpp59WYmKiunfvrhkzZmj16tUnXM/SpUuVnJysuLg4ORwOff75517zhw0bJofD4fXVt29fr8yhQ4c0aNAghYWFKSIiQiNGjFBOTo5XZu3aterevbsCAgIUHx+viRMnVuVtA6gBPiXBisg5Xz4lwaby+T7B+jPifOX7mMsDAAAAVvOtykKvvfaabrnlFg0bNkyxsbHlZqKiovTmm2+ecD25ublq3769brnlFg0YMKDcTN++fTV9+nTPa39/f6/5gwYN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mzdPRUVF6tOnj3Jzc71yt912m1JTUz1fEydOrKEWn3natGnjte+XLVvmmTdmzBjNnj1bs2bN0pIlS7R3714NGDCgBlt75vj555+9+mXevHmSpGuvvdaT4bg5NXJzc9W+fXtNnTq13PkTJ07Uyy+/rGnTpunHH39UcHCwkpKSlJ+f78kMGjRI69ev17x58/TVV19p6dKlGjly5Kl6C6e1E/XPkSNHtHr1aj366KNavXq1Pv30U23cuFFXXHFFmeyTTz7pdTzdfffdp6L5p7WKjh1J6tu3r9d+//DDD73mc+xYp6L++Wu/pKam6q233pLD4dDAgQO9chw71c/M788V/Y5WUlKi/v37q7CwUCtWrNDbb7+tGTNm6LHHHquJt4SKGEA127dvnyHJWLJkiWdajx49jHvuuafmGnUGe/zxx4327duXOy8jI8Pw8/MzZs2a5Zn2xx9/GJKMlStXnqIWotQ999xjNG3a1HC73YZhcNzUFEnGZ5995nntdruNmJgY4/nnn/dMy8jIMPz9/Y0PP/zQMAzD2LBhgyHJ+Pnnnz2Zb775xnA4HMaePXtOWdvPBMf2T3l++uknQ5Kxc+dOz7SEhATjxRdftLZxZ7jy+mbo0KHGlVdeedxlOHZOHTPHzpVXXmlccsklXtM4dk6NY39/NvM72tdff204nU4jLS3Nk3nttdeMsLAwo6Cg4NS+AVSIEW9Uu8zMTElS3bp1vaa///77ql+/vs4++2yNGzdOR44cqYnmnZE2b96suLg4NWnSRIMGDVJKSookadWqVSoqKlLv3r092ZYtW6pRo0ZauXJlTTX3jFRYWKj33ntPt9xyixwOh2c6x03N2759u9LS0ryOk/DwcHXp0sVznKxcuVIRERE655xzPJnevXvL6XTqxx9/POVtPtNlZmbK4XAoIiLCa/qzzz6revXqqWPHjnr++ec5HfMUWbx4saKiotSiRQvdeeedOnjwoGcex459pKena86cORoxYkSZeRw71jv292czv6OtXLlSbdu2VXR0tCeTlJSkrKwsrV+//hS2Hmb41nQDcHpxu9269957deGFF+rss8/2TL/pppuUkJCguLg4rV27Vg899JA2btyoTz/9tAZbe2bo0qWLZsyYoRYtWig1NVVPPPGEunfvrt9//11paWlyuVxlfjmNjo5WWlpazTT4DPX5558rIyNDw4YN80zjuLGH0mPhr7/YlL4unZeWlqaoqCiv+b6+vqpbty7H0imWn5+vhx56SDfeeKPCwsI80//2t7+pU6dOqlu3rlasWKFx48YpNTVVkydPrsHWnv769u2rAQMGKDExUVu3btXDDz+sfv36aeXKlfLx8eHYsZG3335boaGhZS4349ixXnm/P5v5HS0tLa3c/5tK58FeKLxRrUaNGqXff//d6xpiSV7XarVt21axsbHq1auXtm7dqqZNm57qZp5R+vXr5/l3u3bt1KVLFyUkJGjmzJkKDAyswZbhr958803169dPcXFxnmkcN0DlFBUV6brrrpNhGHrttde85o0dO9bz73bt2snlcun222/XhAkT5O/vf6qbesa44YYbPP9u27at2rVrp6ZNm2rx4sXq1atXDbYMx3rrrbc0aNAgBQQEeE3n2LHe8X5/xumFU81RbUaPHq2vvvpKixYtUsOGDU+Y7dKliyRpy5Ytp6Jp+IuIiAidddZZ2rJli2JiYlRYWKiMjAyvTHp6umJiYmqmgWegnTt3av78+br11ltPmOO4qRmlx8Kxd5L963ESExOjffv2ec0vLi7WoUOHOJZOkdKie+fOnZo3b57XaHd5unTpouLiYu3YsePUNBCSpCZNmqh+/fqezzGOHXv4/vvvtXHjxgr/H5I4dqrb8X5/NvM7WkxMTLn/N5XOg71QeOOkGYah0aNH67PPPtPChQuVmJhY4TJr1qyRJMXGxlrcOhwrJydHW7duVWxsrDp37iw/Pz8tWLDAM3/jxo1KSUlR165da7CVZ5bp06crKipK/fv3P2GO46ZmJCYmKiYmxus4ycrK0o8//ug5Trp27aqMjAytWrXKk1m4cKHcbrfnDyawTmnRvXnzZs2fP1/16tWrcJk1a9bI6XSWOc0Z1tq9e7cOHjzo+Rzj2LGHN998U507d1b79u0rzHLsVI+Kfn828zta165dtW7dOq8/XpX+4bF169an5o3ANE41x0kbNWqUPvjgA33xxRcKDQ31XFMSHh6uwMBAbd26VR988IEuu+wy1atXT2vXrtWYMWN00UUXqV27djXc+tPf/fffr+Tk5P9r7/6jar7/OIA/b7/vdasVLSnKr9pthvIjZUUJtTMba0MiWoWRHzU/Rys/zoozv2Y227GVmbFhx5xCM6dakhTKJkIr+RFWhBTT7f39w/H5ukoq3WU8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",
            "text/plain": [
              "<Figure size 1000x600 with 1 Axes>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "# Read the training source file and analyze sentence lengths\n",
        "with open(\"wmt16/train_trg.bpe\", \"r\", encoding=\"utf8\") as file:\n",
        "    lines = file.readlines()\n",
        "\n",
        "# Split each line and calculate lengths\n",
        "lengths = [len(line.strip()) for line in lines]\n",
        "\n",
        "# Create a histogram of sentence lengths\n",
        "plt.figure(figsize=(10, 6))\n",
        "plt.hist(lengths, bins=50, alpha=0.7, color='blue')\n",
        "plt.xlabel('Sentence Length (number of tokens)')\n",
        "plt.ylabel('Frequency')\n",
        "plt.title('Distribution of Sentence Lengths in Training Data')\n",
        "plt.grid(True, alpha=0.3)\n",
        "\n",
        "# Add some statistics as text\n",
        "plt.axvline(np.mean(lengths), color='r', linestyle='dashed', linewidth=1, label=f'Mean: {np.mean(lengths):.2f}')\n",
        "plt.axvline(np.median(lengths), color='g', linestyle='dashed', linewidth=1, label=f'Median: {np.median(lengths):.2f}')\n",
        "plt.legend()\n",
        "\n",
        "# Display some statistics\n",
        "print(f\"Total sentences: {len(lengths)}\")\n",
        "print(f\"Min length: {min(lengths)}\")\n",
        "print(f\"Max length: {max(lengths)}\")\n",
        "print(f\"Mean length: {np.mean(lengths):.2f}\")\n",
        "print(f\"Median length: {np.median(lengths)}\")\n",
        "\n",
        "plt.tight_layout()\n",
        "plt.show()\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "00f8629e",
      "metadata": {
        "id": "00f8629e"
      },
      "source": [
        "# LangPairDataset"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "30745b5f",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "30745b5f",
        "outputId": "b24896af-d565-496f-f627-d23714edd825"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "save cache to wmt16\\.cache\\de2en_train_273.npy\n",
            "save cache to wmt16\\.cache\\de2en_val_273.npy\n"
          ]
        }
      ],
      "source": [
        "from pathlib import Path\n",
        "from torch.utils.data import Dataset, DataLoader\n",
        "\n",
        "\n",
        "\n",
        "class LangPairDataset(Dataset):\n",
        "\n",
        "    def __init__(\n",
        "        self, mode=\"train\", max_length=294, overwrite_cache=False, data_dir=\"wmt16\",\n",
        "    ):\n",
        "        self.data_dir = Path(data_dir) #封装为path对象\n",
        "        cache_path = self.data_dir / \".cache\" / f\"es2en_{mode}_{max_length}.npy\" # 缓存路径\n",
        "\n",
        "        if overwrite_cache or not cache_path.exists(): #判断是否需要覆盖缓存，或者缓存文件不存在\n",
        "            cache_path.parent.mkdir(parents=True, exist_ok=True) # 创建缓存目录\n",
        "\n",
        "            with open(self.data_dir / f\"{mode}_src.bpe\", \"r\", encoding=\"utf8\") as file:\n",
        "                self.src = file.readlines() # 读取源语言文件所有行\n",
        "\n",
        "            with open(self.data_dir / f\"{mode}_trg.bpe\", \"r\", encoding=\"utf8\") as file:\n",
        "                self.trg = file.readlines() # 读取目标语言文件所有行\n",
        "\n",
        "            filtered_src = []\n",
        "            filtered_trg = []\n",
        "            # max length filter,超出最大长度的句子舍弃\n",
        "            for src, trg in zip(self.src, self.trg):\n",
        "                if len(src) <= max_length and len(trg) <= max_length: # 过滤长度超过最大长度的句子\n",
        "                    filtered_src.append(src.strip()) # 去掉句子前后的空格\n",
        "                    filtered_trg.append(trg.strip())\n",
        "            filtered_src = np.array(filtered_src)\n",
        "            filtered_trg = np.array(filtered_trg)\n",
        "            np.save(\n",
        "                cache_path,\n",
        "                {\"src\": filtered_src, \"trg\": filtered_trg },\n",
        "                allow_pickle=True,\n",
        "            )#allow_pickle=True允许保存对象数组，将过滤后的数据保存为 NumPy 数组，存储在缓存文件中\n",
        "            print(f\"save cache to {cache_path}\")\n",
        "\n",
        "        else:\n",
        "            cache_dict = np.load(cache_path, allow_pickle=True).item() #allow_pickle=True允许保存对象数组\n",
        "            print(f\"load {mode} dataset from {cache_path}\")\n",
        "            filtered_src = cache_dict[\"src\"]\n",
        "            filtered_trg = cache_dict[\"trg\"]\n",
        "\n",
        "        self.src = filtered_src\n",
        "        self.trg = filtered_trg\n",
        "\n",
        "    def __getitem__(self, index):\n",
        "        return self.src[index], self.trg[index]\n",
        "\n",
        "    def __len__(self):\n",
        "        return len(self.src)\n",
        "\n",
        "\n",
        "train_ds = LangPairDataset(\"train\")\n",
        "val_ds = LangPairDataset(\"val\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "id": "10296400",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "10296400",
        "outputId": "f04344c6-e6f3-45ad-a017-06dc6741faf5"
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "101118"
            ]
          },
          "execution_count": 6,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "len(train_ds)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "860a6365",
      "metadata": {
        "id": "860a6365"
      },
      "source": [
        "# Vocab词典"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 7,
      "id": "7e42d55f",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 68,
          "referenced_widgets": [
            "8271841f536f476fa7f168285169b8b0",
            "d04403d6d9de45229ab199c84d8e78b1",
            "83516e53d8044b5984c31b0cfa983454",
            "4111b8dea92d4c73a0d797c900d1c4e4",
            "110a1f620812433692b0442ba588013c",
            "a81f6c3bb6a4482b86d028d608b04559",
            "32ab830293104d33b6f584b0ed030aeb",
            "114607d303c64d558617e41975b25270",
            "9aca93d3cde5487c8d83e9007673f227",
            "e78c6667146541fdb695db5690fa4301",
            "17b7154badac4cae83ae11e0bbc8f881"
          ]
        },
        "id": "7e42d55f",
        "outputId": "56ced5ee-1926-4f3f-af5e-567c4918394c"
      },
      "outputs": [
        {
          "data": {
            "application/vnd.jupyter.widget-view+json": {
              "model_id": "f2c149ecdabe4617abadf8872e54334b",
              "version_major": 2,
              "version_minor": 0
            },
            "text/plain": [
              "  0%|          | 0/27013 [00:00<?, ?it/s]"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "vocab_size: 27017\n"
          ]
        }
      ],
      "source": [
        "#载入词表，看下词表长度，词表就像英语字典,构建word2idx和idx2word\n",
        "word2idx = {\n",
        "    \"[PAD]\": 0,     # 填充 token\n",
        "    \"[BOS]\": 1,     # begin of sentence\n",
        "    \"[UNK]\": 2,     # 未知 token\n",
        "    \"[EOS]\": 3,     # end of sentence\n",
        "}\n",
        "idx2word = {value: key for key, value in word2idx.items()}\n",
        "index = len(idx2word)\n",
        "threshold = 1  # 出现次数低于此的token舍弃\n",
        "\n",
        "with open(\"wmt16/vocab\", \"r\", encoding=\"utf8\") as file:  # 打开词汇表文件进行读取，使用utf8编码\n",
        "    for line in tqdm(file.readlines()):  # 使用tqdm显示进度条，遍历文件的每一行\n",
        "        token, counts = line.strip().split()  # 去除每行两端的空白字符并按空格分割为token和出现次数\n",
        "        if int(counts) >= threshold:  # 判断token的出现次数是否大于或等于阈值\n",
        "            word2idx[token] = index  # 将token添加到word2idx字典，建立token到索引的映射\n",
        "            idx2word[index] = token  # 将token添加到idx2word字典，建立索引到token的映射\n",
        "            index += 1  # 索引值增加1，为下一个token准备\n",
        "\n",
        "vocab_size = len(word2idx)  # 计算词表大小，即word2idx字典中的条目数量\n",
        "print(\"vocab_size: {}\".format(vocab_size))  # 打印词表大小\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "9e77c79c",
      "metadata": {
        "id": "9e77c79c"
      },
      "source": [
        "# Tokenizer"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 8,
      "id": "656066ff",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "656066ff",
        "outputId": "6f6b6771-6a1a-4d02-9ba1-0f085f7550c8"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "raw text\n",
            "['hello', 'world']\n",
            "['a', 'little', 'boy', 'playing', 'gam@@', 'e@@', 'cu@@', 'be', 'at', 'a', 'mcdonald', '&apos;s', '.']\n",
            "['this', 'is', 'a', 'test']\n",
            "indices\n",
            "tensor([   1, 4091,  571,    3,    0,    0,    0,    0,    0,    0,    0,    0,\n",
            "           0,    0,    0])\n",
            "tensor([    1,     6,   309,   473,   703, 24840,  1990,  2748,    61,    71,\n",
            "            6,  8044,    28,     4,     3])\n",
            "tensor([   1,   38,   19,    6, 1628,    3,    0,    0,    0,    0,    0,    0,\n",
            "           0,    0,    0])\n",
            "decode text\n",
            "[BOS] hello world [EOS] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD]\n",
            "[BOS] a little boy playing gam@@ e@@ cu@@ be at a mcdonald &apos;s . [EOS]\n",
            "[BOS] this is a test [EOS] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD]\n"
          ]
        }
      ],
      "source": [
        "class Tokenizer:\n",
        "    def __init__(self, word2idx, idx2word, max_length=128, pad_idx=0, bos_idx=1, eos_idx=3, unk_idx=2):\n",
        "        self.word2idx = word2idx\n",
        "        self.idx2word = idx2word\n",
        "        self.max_length = max_length\n",
        "        self.pad_idx = pad_idx\n",
        "        self.bos_idx = bos_idx\n",
        "        self.eos_idx = eos_idx\n",
        "        self.unk_idx = unk_idx\n",
        "\n",
        "    def encode(self, text_list, padding_first=False, add_bos=True, add_eos=True, return_mask=False):\n",
        "        \"\"\"如果padding_first == True，则padding加载前面，否则加载后面\"\"\"\n",
        "        max_length = min(self.max_length, add_eos + add_bos + max([len(text) for text in text_list]))\n",
        "        indices_list = []\n",
        "        #text_list是句子列表，每个句子是一个单词列表,text_list是一个批次\n",
        "        for text in text_list:\n",
        "            indices = [self.word2idx.get(word, self.unk_idx) for word in text[:max_length - add_bos - add_eos]]\n",
        "            if add_bos:#如果add_bos == True，则添加[BOS]\n",
        "                indices = [self.bos_idx] + indices\n",
        "            if add_eos:#如果add_eos == True，则添加[EOS]\n",
        "                indices = indices + [self.eos_idx]\n",
        "            if padding_first:#如果padding_first == True，则padding加载前面，否则加载后面\n",
        "                indices = [self.pad_idx] * (max_length - len(indices)) + indices\n",
        "            else:\n",
        "                indices = indices + [self.pad_idx] * (max_length - len(indices))\n",
        "            indices_list.append(indices)\n",
        "        input_ids = torch.tensor(indices_list)\n",
        "        masks = (input_ids == self.pad_idx).to(dtype=torch.int64) # 为了方便损失计算，这里的mask为0的地方需要计算，为1的地方不需要计算\n",
        "        return input_ids if not return_mask else (input_ids, masks)\n",
        "\n",
        "\n",
        "    def decode(self, indices_list, remove_bos=True, remove_eos=True, remove_pad=True, split=False):\n",
        "        text_list = []\n",
        "        for indices in indices_list:\n",
        "            text = []\n",
        "            for index in indices:\n",
        "                word = self.idx2word.get(index, \"[UNK]\")\n",
        "                if remove_bos and word == \"[BOS]\":\n",
        "                    continue\n",
        "                if remove_eos and word == \"[EOS]\":\n",
        "                    break\n",
        "                if remove_pad and word == \"[PAD]\":\n",
        "                    break\n",
        "                text.append(word)\n",
        "            text_list.append(\" \".join(text) if not split else text) #如果split == True，则返回一个单词列表，否则返回一个句子\n",
        "        return text_list #返回一个句子列表\n",
        "\n",
        "\n",
        "tokenizer = Tokenizer(word2idx=word2idx, idx2word=idx2word)\n",
        "\n",
        "\n",
        "raw_text = [\"hello world\".split(), \"a little boy playing gam@@ e@@ cu@@ be at a mcdonald &apos;s .\".split(), \"this is a test\".split()]\n",
        "indices = tokenizer.encode(raw_text, padding_first=False, add_bos=True, add_eos=True)\n",
        "decode_text = tokenizer.decode(indices.tolist(), remove_bos=False, remove_eos=False, remove_pad=False)\n",
        "print(\"raw text\")\n",
        "for raw in raw_text:\n",
        "    print(raw)\n",
        "print(\"indices\")\n",
        "for index in indices:\n",
        "    print(index)\n",
        "print(\"decode text\")\n",
        "for decode in decode_text:\n",
        "    print(decode)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 9,
      "id": "8ef05ff7",
      "metadata": {
        "id": "8ef05ff7"
      },
      "outputs": [],
      "source": [
        "class SampleInfo: #下面的info对象\n",
        "    def __init__(self, i, lens):\n",
        "        \"\"\"\n",
        "        记录文本对的序号和长度信息\n",
        "        输入：\n",
        "            - i (int): 文本对的序号。\n",
        "            - lens (list): 文本对源语言和目标语言的长度\n",
        "        \"\"\"\n",
        "        self.i = i\n",
        "        # 加一是考虑填补在文本前后的特殊词元，lens[0]和lens[1]分别表示源语言和目标语言的长度\n",
        "        self.max_len = max(lens[0], lens[1]) + 1\n",
        "        # self.max_len = lens[0] + 1\n",
        "        self.src_len = lens[0] + 1\n",
        "        self.trg_len = lens[1] + 1\n",
        "\n",
        "# 一个批量生成器，根据词元数目的限制来控制批量的大小。它会根据传入的样本信息，在不超过设定大小的情况下，逐步构建批量。\n",
        "#就是箱子\n",
        "class TokenBatchCreator:\n",
        "    def __init__(self, batch_size):\n",
        "        \"\"\"\n",
        "        参数:\n",
        "        batch_size (int): 用于限制批量的大小。箱子大小 高*宽\n",
        "        功能:\n",
        "        初始化了一个空的批量列表 _batch。\n",
        "        设定了初始的最大长度为 -1。\n",
        "        存储了传入的 batch_size。\n",
        "        \"\"\"\n",
        "\n",
        "        self.__batch = []  #这个就是之前的batch_size，就是第一个batch内有多少个样本\n",
        "        self.max_len = -1  #箱子内最长的样本长度\n",
        "        self._batch_size = batch_size # 限制批量的大小,假设是4096\n",
        "\n",
        "    def append(self, info: SampleInfo):\n",
        "        \"\"\"\n",
        "        参数:\n",
        "        info (SampleInfo): 文本对的信息。\n",
        "        功能:\n",
        "        接收一个 SampleInfo 对象，并根据其最大长度信息更新当前批量的最大长度。\n",
        "        如果将新的样本加入批量后超过了批量大小限制，它会返回已有的批量并将新的样本加入新的批量。\n",
        "        否则，它会更新最大长度并将样本添加到当前批量中。\n",
        "        \"\"\"\n",
        "        # 更新当前批量的最大长度\n",
        "        cur_len = info.max_len # 当前样本的长度\n",
        "        max_len = max(self.max_len, cur_len) # 每来一个样本，更新当前批次的最大长度\n",
        "        # 如果新的样本加入批量后超过大小限制，则将已有的批量返回，新的样本加入新的批量\n",
        "        if max_len * (len(self.__batch) + 1) > self._batch_size:\n",
        "            self.__batch, result = [], self.__batch # 保存当前的batch，并返回,这里的result是之前的batch,_batch清空\n",
        "            self.__batch.append(info) #箱子里的第一条样本，放入\n",
        "            self.max_len = cur_len #因为是当前batch的第一个样本，所以它的长度就是当前长度\n",
        "            return result\n",
        "        else:\n",
        "            self.max_len = max_len\n",
        "            self.__batch.append(info) # 将样本添加到当前批量中\n",
        "            return None\n",
        "\n",
        "    @property\n",
        "    def batch(self):\n",
        "        return self.__batch"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 10,
      "id": "f2f41c51",
      "metadata": {
        "id": "f2f41c51"
      },
      "outputs": [],
      "source": [
        "# 当一个自定义对象可以iter(自定义对象)时，会自动调用__iter__方法\n",
        "from torch.utils.data import BatchSampler\n",
        "import numpy as np\n",
        "\n",
        "\n",
        "class TransformerBatchSampler(BatchSampler):\n",
        "    def __init__(self,\n",
        "                 dataset,\n",
        "                 batch_size,\n",
        "                 shuffle_batch=False,\n",
        "                 clip_last_batch=False,\n",
        "                 seed=0):\n",
        "        \"\"\"\n",
        "        批量采样器\n",
        "        输入:\n",
        "            - dataset: 数据集\n",
        "            - batch_size: 批量大小\n",
        "            - shuffle_batch: 是否对生成的批量进行洗牌\n",
        "            - clip_last_batch: 是否裁剪最后剩下的数据\n",
        "            - seed: 随机数种子\n",
        "        \"\"\"\n",
        "        self._dataset = dataset #数据集\n",
        "        self._batch_size = batch_size #箱子大小\n",
        "        self._shuffle_batch = shuffle_batch #是否打乱箱子\n",
        "        self._clip_last_batch = clip_last_batch #是否裁剪最后剩下的数据\n",
        "        self._seed = seed #下面3个是为了随机\n",
        "        self._random = np.random\n",
        "        self._random.seed(seed)\n",
        "\n",
        "        self._sample_infos = [] #所有样本信息\n",
        "        # 根据数据集中的每个样本，创建了对应的 SampleInfo 对象，包含了样本的索引和长度信息。\n",
        "        for i, data in enumerate(self._dataset):\n",
        "            lens = [len(data[0]), len(data[1])] #输入和输出的长度计算放到lens中\n",
        "            self._sample_infos.append(SampleInfo(i, lens)) #每个样本信息\n",
        "\n",
        "    def __iter__(self):\n",
        "        \"\"\"\n",
        "        对数据集中的样本进行排序，排序规则是先按源语言长度排序，如果相同则按目标语言长度排序。\n",
        "        使用 TokenBatchCreator 逐步组装批量数据，当满足批量大小时返回一个批量的样本信息。\n",
        "        如果不裁剪最后一个批次的数据且存在剩余样本，则将这些样本组成最后一个批次。\n",
        "        如果需要对批量进行洗牌，则对批次进行洗牌操作。\n",
        "        通过迭代器，抛出每个批量的样本在数据集中的索引。\n",
        "        \"\"\"\n",
        "        # 排序，如果源语言长度相同则按照目标语言的长度排列\n",
        "        infos = sorted(self._sample_infos,\n",
        "                       key=lambda x: (x.src_len, x.trg_len))\n",
        "        # 把样本放入到箱子里，所有装箱后的箱子，每一个箱子都放入batch_infos\n",
        "        batch_infos = [] #放箱子的列表，每个箱子都是一个batch\n",
        "        batch_creator = TokenBatchCreator(self._batch_size) # 批量生成器,上面自定义的类\n",
        "        for info in infos:\n",
        "            batch = batch_creator.append(info)\n",
        "            # 存够一个batch的样本信息后，会把这个batch返回，否则返回为None\n",
        "            if batch is not None:\n",
        "                batch_infos.append(batch)\n",
        "\n",
        "        # 是否抛弃最后批量的文本对\n",
        "        if not self._clip_last_batch and len(batch_creator.batch) != 0:\n",
        "            batch_infos.append(batch_creator.batch) # 最后一个batch\n",
        "\n",
        "        # 打乱batch，打乱的是箱子的顺序\n",
        "        if self._shuffle_batch:\n",
        "            self._random.shuffle(batch_infos)\n",
        "\n",
        "        self.batch_number = len(batch_infos) #箱子数量\n",
        "        # print(self.batch_number) #为了理解\n",
        "\n",
        "        # 抛出一个箱子里所有样本的序号\n",
        "        for batch in batch_infos:\n",
        "            batch_indices = [info.i for info in batch] # 批量的样本在数据集中的索引，第一个batch[0,1,.....82]，第二个batch[83,84,85,86,87]\n",
        "            yield batch_indices\n",
        "\n",
        "    def __len__(self):\n",
        "        \"\"\"\n",
        "        返回批量的数量\n",
        "        \"\"\"\n",
        "        if hasattr(self, \"batch_number\"):\n",
        "            return self.batch_number\n",
        "        # 计算批量的数量,没有用到下面的情况，不用看\n",
        "        batch_number = (len(self._dataset) +\n",
        "                        self._batch_size) // self._batch_size\n",
        "        return batch_number"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 11,
      "id": "d9fcba5b",
      "metadata": {
        "id": "d9fcba5b"
      },
      "outputs": [],
      "source": [
        "sampler = TransformerBatchSampler(train_ds, batch_size=4096, shuffle_batch=True)\n",
        "\n",
        "#为什么这里每个批量的样本对数目不一样呢？长度*batch_number>4096的时候，就会返回上一个batch，然后新的样本加入新的batch,具体要看TokenBatchCreator的44行"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 12,
      "id": "5e7a5d82",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "5e7a5d82",
        "outputId": "0a897fa9-68e5-4d61-d605-a89560a8f44b"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "第0批量的数据中含有文本对是：[9157, 9187, 9452, 10131, 10233, 10437, 11723, 11827, 12281, 13570, 13782, 13791, 14106, 14442, 14896, 16682, 16808, 16821, 17781, 18299, 18985, 19120, 19782, 21569, 21764, 22063, 22093, 22331, 22621, 23535, 23692, 23830, 24136, 24151, 24199, 24912, 25758, 26382, 26765, 27161, 27861, 27908, 30119, 30172, 31839, 31894, 31992, 32832, 33029, 33588, 33763, 33828, 33971, 34347, 35446, 35536, 36250, 36926, 37093, 38755, 39363, 40265, 40985, 41354, 41449, 41645, 42388, 43453, 47729, 48948, 49668, 49846, 51679, 52982, 53647, 53905, 54270, 54388, 54459, 55185, 55268, 55522, 56289, 57320, 58089, 58190, 58806, 60012, 60322, 60782, 61689, 61710, 62517, 62519, 63624, 64447, 65403, 65694, 66248, 67057, 67614, 68469, 68863, 69044, 70645, 71196, 73502, 73768, 74100, 74423, 74474, 74799, 74908]，数量为：113\n",
            "第1批量的数据中含有文本对是：[6675, 14700, 14827, 61171, 39771, 17340, 54965, 69957, 12020, 45328, 83227, 90730, 54792, 75139, 78908, 66936, 12256, 11518, 89176, 41018, 58215, 52236, 97359, 8761, 15409, 90384, 82003, 34709, 50512, 58378, 43028, 58115, 72871]，数量为：33\n",
            "第2批量的数据中含有文本对是：[4837, 12233, 12567, 16562, 19925, 23268, 32454, 63436, 70433, 73419, 78098, 82539, 83144, 83385, 84786, 87706, 91943, 93348, 97351, 99637, 6384, 16080, 18416, 21797, 24475, 34022, 37050, 46468, 47018, 51918, 56538, 62066, 64663, 65061, 75098, 79103, 87954, 89256, 93590, 94546, 27807, 30597, 42893, 49132, 50336, 56013, 61933, 64597, 66115, 72055, 2086, 14583, 22134, 47565, 53381, 66373, 9666, 13574, 52490, 57760, 58899, 73646, 81106, 100493, 13007, 50082, 58915, 61963, 93299, 12027, 18440, 82852, 72697, 100353, 26268, 21138, 10872, 29663, 91911, 92583, 8349, 15114, 58317]，数量为：83\n",
            "第3批量的数据中含有文本对是：[64991, 65179, 65374, 66004, 66254, 67116, 69313, 74927, 75387, 76798, 80861, 81434, 82803, 83952, 86465, 86936, 87842, 95962, 96626, 97059, 98516, 99098, 100533, 993, 4234, 5116, 11533, 12923, 13633, 14683, 15817, 16028, 17592, 17605, 18830, 21133, 26035, 26175, 30160, 31196, 32182, 32535, 33837, 34217, 37570, 39541, 39749, 40343, 43967, 49143, 49602, 53084, 53679, 53785, 57556, 60523, 61474, 61845, 63585, 65094, 67194, 69037, 69599, 71338, 71978, 71993, 74775, 75037, 76574, 76809, 78033, 79085, 79733, 80762, 81618, 87407, 89537, 92217, 93071, 93662, 97501, 98561, 764, 1385, 1594, 2976, 4008]，数量为：87\n"
          ]
        }
      ],
      "source": [
        "for idx, batch in enumerate(sampler):\n",
        "    print(\"第{}批量的数据中含有文本对是：{}，数量为：{}\".format(idx, batch, len(batch)))\n",
        "    if idx >= 3:\n",
        "        break"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "9a8adf5a",
      "metadata": {
        "id": "9a8adf5a"
      },
      "source": [
        "# DataLoader"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 13,
      "id": "b1d2c67e",
      "metadata": {
        "id": "b1d2c67e"
      },
      "outputs": [],
      "source": [
        "def collate_fct(batch, tokenizer):\n",
        "    src_words = [pair[0].split() for pair in batch]\n",
        "    trg_words = [pair[1].split() for pair in batch]\n",
        "\n",
        "    # [BOS] src [EOS] [PAD]\n",
        "    encoder_inputs, encoder_inputs_mask = tokenizer.encode(\n",
        "        src_words, padding_first=False, add_bos=True, add_eos=True, return_mask=True\n",
        "        )\n",
        "\n",
        "    # [BOS] trg [PAD]\n",
        "    decoder_inputs = tokenizer.encode(\n",
        "        trg_words, padding_first=False, add_bos=True, add_eos=False, return_mask=False,\n",
        "        )\n",
        "\n",
        "    # trg [EOS] [PAD]\n",
        "    decoder_labels, decoder_labels_mask = tokenizer.encode(\n",
        "        trg_words, padding_first=False, add_bos=False, add_eos=True, return_mask=True\n",
        "        )\n",
        "\n",
        "    return {\n",
        "        \"encoder_inputs\": encoder_inputs.to(device=device),\n",
        "        \"encoder_inputs_mask\": encoder_inputs_mask.to(device=device),\n",
        "        \"decoder_inputs\": decoder_inputs.to(device=device),\n",
        "        \"decoder_labels\": decoder_labels.to(device=device),\n",
        "        \"decoder_labels_mask\": decoder_labels_mask.to(device=device),\n",
        "    }\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 14,
      "id": "17f23bfe",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "17f23bfe",
        "outputId": "95bfb3e2-bc1b-426f-b54e-6f7d347cd008"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "encoder_inputs\n",
            "tensor([[    1,   409,  2353,  1299,    22,    47,   195,     4,     3,     0],\n",
            "        [    1,    16,     6,    55,   300,   710,    17,  9769,     8,     3],\n",
            "        [    1,  2604,    17,  1229,    12,  3958,    12,  8060,     4,     3],\n",
            "        [    1,  1571,   104,  1457,    51,    17,  1013,     4,     3,     0],\n",
            "        [    1,    13,    23,   488,     6,     5,  3284,     4,     3,     0],\n",
            "        [    1,   919,    54,   138, 13814,    47,  1344,     4,     3,     0],\n",
            "        [    1,     5,    24,    25, 12776, 22907,     4,     3,     0,     0]])\n",
            "encoder_inputs_mask\n",
            "tensor([[0, 0, 0, 0, 0, 0, 0, 0, 0, 1],\n",
            "        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n",
            "        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n",
            "        [0, 0, 0, 0, 0, 0, 0, 0, 0, 1],\n",
            "        [0, 0, 0, 0, 0, 0, 0, 0, 0, 1],\n",
            "        [0, 0, 0, 0, 0, 0, 0, 0, 0, 1],\n",
            "        [0, 0, 0, 0, 0, 0, 0, 0, 1, 1]])\n",
            "decoder_inputs\n",
            "tensor([[    1,     7,   552,    11,  1720,    27,    58,   206,     4,     0],\n",
            "        [    1,    45,    89,   234,     9, 11645,   127,     8,     0,     0],\n",
            "        [    1,     7,    34,  1026,    60,  4001,  1229,    20,  8060,     4],\n",
            "        [    1,   266,    34,  1335,   102,     9,   863,     4,     0,     0],\n",
            "        [    1,     7,   637,    21,   495,     5,  5261,     4,     0,     0],\n",
            "        [    1,   954,    74, 18828,    57,  1436,     4,     0,     0,     0],\n",
            "        [    1,     5,    19,     6, 24998, 12403, 19773,     4,     0,     0]])\n",
            "decoder_labels\n",
            "tensor([[    7,   552,    11,  1720,    27,    58,   206,     4,     3,     0],\n",
            "        [   45,    89,   234,     9, 11645,   127,     8,     3,     0,     0],\n",
            "        [    7,    34,  1026,    60,  4001,  1229,    20,  8060,     4,     3],\n",
            "        [  266,    34,  1335,   102,     9,   863,     4,     3,     0,     0],\n",
            "        [    7,   637,    21,   495,     5,  5261,     4,     3,     0,     0],\n",
            "        [  954,    74, 18828,    57,  1436,     4,     3,     0,     0,     0],\n",
            "        [    5,    19,     6, 24998, 12403, 19773,     4,     3,     0,     0]])\n",
            "decoder_labels_mask\n",
            "tensor([[0, 0, 0, 0, 0, 0, 0, 0, 0, 1],\n",
            "        [0, 0, 0, 0, 0, 0, 0, 0, 1, 1],\n",
            "        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n",
            "        [0, 0, 0, 0, 0, 0, 0, 0, 1, 1],\n",
            "        [0, 0, 0, 0, 0, 0, 0, 0, 1, 1],\n",
            "        [0, 0, 0, 0, 0, 0, 0, 1, 1, 1],\n",
            "        [0, 0, 0, 0, 0, 0, 0, 0, 1, 1]])\n"
          ]
        }
      ],
      "source": [
        "from functools import partial # 固定collate_fct的tokenizer参数\n",
        "\n",
        "#可以调大batch_size,来看最终的bleu，如果GPU内存不够，可以减小batch_size\n",
        "sampler = TransformerBatchSampler(train_ds, batch_size=256, shuffle_batch=True)\n",
        "# https://pytorch.org/docs/stable/data.html#torch.utils.data.DataLoader\n",
        "sample_dl = DataLoader(train_ds, batch_sampler=sampler, collate_fn=partial(collate_fct, tokenizer=tokenizer)) #partial函数，固定collate_fct的tokenizer参数\n",
        "\n",
        "for batch in sample_dl:#外层是拿每个batch\n",
        "    for key, value in batch.items():#内层是拿每个batch里面是一个字典\n",
        "        print(key)\n",
        "        print(value)\n",
        "    break"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "597b9d2c",
      "metadata": {
        "id": "597b9d2c"
      },
      "source": [
        "# 定义模型\n",
        "- Transformer模型由Embedding、Transformer-Block组成\n",
        "- Embedding包括：\n",
        "    - WordEmbedding\n",
        "    - PositionEmbedding\n",
        "- 多头注意力\n",
        "- Transformer-Block包括：\n",
        "    - Self-Attention\n",
        "    - Cross-Attention\n",
        "    - MLP"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 15,
      "id": "158da269",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "158da269",
        "outputId": "743b3b43-d35a-4144-cd49-2ef9169988fd"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "tensor(0.0100)\n"
          ]
        }
      ],
      "source": [
        "import torch\n",
        "import math\n",
        "\n",
        "def positional_encoding_weights(emb_size):\n",
        "    # 计算底数和指数\n",
        "    base = math.log(10000)\n",
        "    exponent = -5 / emb_size\n",
        "\n",
        "    # 应用指数函数\n",
        "    # 将 base 转换为 tensor，因为 torch.exp 需要 tensor 类型的输入\n",
        "    weight = torch.exp(torch.tensor(base)*exponent)\n",
        "\n",
        "    return weight\n",
        "\n",
        "emb_size = 10  # 举例，可以替换成你需要的大小\n",
        "weight = positional_encoding_weights(emb_size)\n",
        "print(weight)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "c7335220",
      "metadata": {
        "id": "c7335220"
      },
      "source": [
        "## TransformerEmbedding"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 16,
      "id": "bbb0dfb5",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "bbb0dfb5",
        "outputId": "d951c5c8-42f4-4c03-c630-1dfaa8ec8535"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "输入形状: torch.Size([2, 10])\n",
            "输出形状: torch.Size([2, 10, 128])\n"
          ]
        }
      ],
      "source": [
        "import torch\n",
        "import torch.nn as nn\n",
        "import math\n",
        "\n",
        "class TransformerEmbedding(nn.Module):\n",
        "    def __init__(self, config):\n",
        "        super().__init__()\n",
        "        self.vocab_size = config[\"vocab_size\"]\n",
        "        self.hidden_size = config[\"d_model\"]  # 词向量维度\n",
        "        self.pad_idx = config[\"pad_idx\"]\n",
        "        self.max_length = config[\"max_length\"] # 最大token长度\n",
        "        dropout_rate = config[\"dropout\"]  # 随机失活率\n",
        "\n",
        "        # 词嵌入层\n",
        "        self.word_embedding = nn.Embedding(\n",
        "            num_embeddings=self.vocab_size,\n",
        "            embedding_dim=self.hidden_size,\n",
        "            padding_idx=self.pad_idx\n",
        "        )\n",
        "\n",
        "        # 位置编码层 - 不需要训练\n",
        "        self.position_embedding = nn.Embedding(\n",
        "            num_embeddings=self.max_length,\n",
        "            embedding_dim=self.hidden_size\n",
        "        )\n",
        "\n",
        "        # 初始化位置编码，固定不训练\n",
        "        self.register_buffer(\n",
        "            \"position_ids\", torch.arange(self.max_length).expand((1, -1))\n",
        "        )\n",
        "        self.position_embedding.weight.requires_grad = False # 位置编码不需要训练\n",
        "        self._init_position_encoding() # 初始化位置编码\n",
        "\n",
        "        self.dropout = nn.Dropout(dropout_rate)\n",
        "\n",
        "    def _init_position_encoding(self):\n",
        "        \"\"\"初始化位置编码权重\"\"\"\n",
        "        position = torch.arange(self.max_length).unsqueeze(1)\n",
        "        div_term = torch.exp(torch.arange(0, self.hidden_size, 2) * (-math.log(10000.0) / self.hidden_size))\n",
        "\n",
        "        position_encoding = torch.zeros(self.max_length, self.hidden_size)\n",
        "        position_encoding[:, 0::2] = torch.sin(position * div_term)\n",
        "        position_encoding[:, 1::2] = torch.cos(position * div_term)\n",
        "\n",
        "        self.position_embedding.weight.data.copy_(position_encoding)\n",
        "\n",
        "    def forward(self, x):\n",
        "        seq_length = x.size(1)\n",
        "\n",
        "        # 词嵌入\n",
        "        word_embeddings = self.word_embedding(x)\n",
        "\n",
        "        # 位置编码\n",
        "        position_ids = self.position_ids[:, :seq_length]\n",
        "        position_embeddings = self.position_embedding(position_ids)\n",
        "\n",
        "        # 词嵌入 + 位置编码\n",
        "        embeddings = word_embeddings + position_embeddings\n",
        "\n",
        "        # 应用dropout\n",
        "        embeddings = self.dropout(embeddings)\n",
        "\n",
        "        return embeddings\n",
        "# %% cell 23 code\n",
        "\n",
        "# 初始化TransformerEmbedding并进行前向计算\n",
        "config = {\n",
        "    'vocab_size': 30000,\n",
        "    'd_model': 128,\n",
        "    'max_length': 64,\n",
        "    'pad_idx': 0,\n",
        "    'dropout': 0.1,\n",
        "}\n",
        "\n",
        "# 创建模型实例\n",
        "embedding_model = TransformerEmbedding(config=config)\n",
        "\n",
        "# 创建一个示例输入 (batch_size=2, seq_length=10)\n",
        "sample_input = torch.randint(0, config['vocab_size'], (2, 10))\n",
        "print(f\"输入形状: {sample_input.shape}\")\n",
        "\n",
        "# 前向计算\n",
        "output = embedding_model(sample_input)\n",
        "print(f\"输出形状: {output.shape}\")\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 17,
      "id": "4e625af9",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 455
        },
        "id": "4e625af9",
        "outputId": "d7b1f664-1af9-4773-9812-eb71bb6191bc"
      },
      "outputs": [
        {
          "data": {
            "image/png": "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",
            "text/plain": [
              "<Figure size 640x480 with 2 Axes>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "def plot_position_embedding(position_embedding):# 绘制位置编码\n",
        "    plt.pcolormesh(position_embedding) # 绘制位置编码矩阵\n",
        "    plt.xlabel('Depth')\n",
        "    plt.ylabel('Position')\n",
        "    plt.colorbar() # 颜色条，-1到1的颜色范围\n",
        "    plt.show()\n",
        "\n",
        "# 创建TransformerEmbedding实例并绘制位置编码\n",
        "config = {\n",
        "    'vocab_size': 30000,\n",
        "    'd_model': 128,\n",
        "    'max_length': 64,\n",
        "    'pad_idx':0,\n",
        "    'dropout':0.1,\n",
        "}\n",
        "embedding_model = TransformerEmbedding(config=config)\n",
        "position_embedding_data = embedding_model.position_embedding.weight.data\n",
        "plot_position_embedding(position_embedding_data)\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "6b85c5f6",
      "metadata": {
        "id": "6b85c5f6"
      },
      "source": [
        "## MultiHeadAttention(缩放点积注意力)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 18,
      "id": "99623244",
      "metadata": {
        "id": "99623244"
      },
      "outputs": [],
      "source": [
        "from dataclasses import dataclass\n",
        "\n",
        "\n",
        "Tensor = torch.Tensor\n",
        "@dataclass\n",
        "class AttentionOutput:\n",
        "    hidden_states: Tensor\n",
        "    attn_scores: Tensor\n",
        "\n",
        "class MultiHeadAttention(nn.Module):\n",
        "    def __init__(self, config):\n",
        "        super().__init__()\n",
        "        self.hidden_size = config[\"d_model\"]  # 隐藏层大小\n",
        "        self.num_heads = config[\"num_heads\"]  # 多头注意力的头数\n",
        "\n",
        "        # 确保hidden_size可以被num_heads整除\n",
        "        assert self.hidden_size % self.num_heads == 0, \"hidden_size must be divisible by num_heads\"\n",
        "\n",
        "        # 每个头的维度,512/8=64\n",
        "        self.depth = self.hidden_size // self.num_heads\n",
        "\n",
        "        # 创建四个线性变换层\n",
        "        self.Wq = nn.Linear(self.hidden_size, self.hidden_size)\n",
        "        self.Wk = nn.Linear(self.hidden_size, self.hidden_size)\n",
        "        self.Wv = nn.Linear(self.hidden_size, self.hidden_size)\n",
        "        self.Wo = nn.Linear(self.hidden_size, self.hidden_size)\n",
        "\n",
        "    def split_heads(self, x, batch_size):\n",
        "        \"\"\"\n",
        "        将输入张量分割成多个头\n",
        "        x shape: (batch_size, seq_len, hidden_size)\n",
        "        返回 shape: (batch_size, num_heads, seq_len, depth)\n",
        "        \"\"\"\n",
        "        # 重塑为 (batch_size, seq_len, num_heads, depth)\n",
        "        x = x.view(batch_size, -1, self.num_heads, self.depth)\n",
        "        # 转置为 (batch_size, num_heads, seq_len, depth)\n",
        "        return x.permute(0, 2, 1, 3)\n",
        "\n",
        "    def merge_heads(self, x, batch_size):\n",
        "        \"\"\"\n",
        "        将多头注意力的输出合并\n",
        "        x shape: (batch_size, num_heads, seq_len, depth)\n",
        "        返回 shape: (batch_size, seq_len, hidden_size)\n",
        "        \"\"\"\n",
        "        # (batch_size, num_heads, seq_len, depth) 转置回 (batch_size, seq_len, num_heads, depth)\n",
        "        x = x.permute(0, 2, 1, 3)\n",
        "        # 重塑为 (batch_size, seq_len, hidden_size)\n",
        "        return x.reshape(batch_size, -1, self.hidden_size)\n",
        "\n",
        "    def scaled_dot_product_attention(self, Q, K, V, mask=None):\n",
        "        \"\"\"\n",
        "        计算缩放点积注意力\n",
        "        Q, K, V shape: (batch_size, num_heads, seq_len, depth)\n",
        "        mask shape: (batch_size, 1, 1, seq_len) 或 (batch_size, 1, seq_len, seq_len)\n",
        "        \"\"\"\n",
        "        # 计算注意力分数\n",
        "        matmul_qk = torch.matmul(Q, K.transpose(-2, -1))  # (batch_size, num_heads, seq_len_q, seq_len_k)\n",
        "\n",
        "        # 缩放\n",
        "        dk = torch.tensor(self.depth, dtype=torch.float32)\n",
        "        scaled_attention_logits = matmul_qk / torch.sqrt(dk)\n",
        "        # print(f'scaled_attention_logits.shape:{scaled_attention_logits.shape}')\n",
        "        # print(f'mask.shape{mask.shape}')\n",
        "        # 应用掩码（如果提供）\n",
        "        if mask is not None:\n",
        "            scaled_attention_logits += (mask * -1e9)\n",
        "\n",
        "        # softmax归一化\n",
        "        attention_weights = F.softmax(scaled_attention_logits, dim=-1)  # (batch_size, num_heads, seq_len_q, seq_len_k)\n",
        "\n",
        "        # 应用注意力权重\n",
        "        #(batch_size, num_heads, seq_len_q, seq_len_k) * (batch_size, num_heads, seq_len_v, depth) = (batch_size, num_heads, seq_len_q, depth)\n",
        "        output = torch.matmul(attention_weights, V)  # (batch_size, num_heads, seq_len_q, depth)\n",
        "\n",
        "        return output, attention_weights\n",
        "\n",
        "    def forward(self, Q, K, V, mask=None):\n",
        "        \"\"\"\n",
        "        入参Q,K,V都是X\n",
        "        \"\"\"\n",
        "        batch_size = Q.shape[0]\n",
        "\n",
        "        # 线性变换\n",
        "        Q = self.Wq(Q)  # (batch_size, seq_len_q, hidden_size)\n",
        "        K = self.Wk(K)  # (batch_size, seq_len_k, hidden_size)\n",
        "        V = self.Wv(V)  # (batch_size, seq_len_v, hidden_size)\n",
        "\n",
        "        # 分割成多头\n",
        "        Q = self.split_heads(Q, batch_size)  # (batch_size, num_heads, seq_len_q, depth)\n",
        "        K = self.split_heads(K, batch_size)  # (batch_size, num_heads, seq_len_k, depth)\n",
        "        V = self.split_heads(V, batch_size)  # (batch_size, num_heads, seq_len_v, depth)\n",
        "\n",
        "        # 计算缩放点积注意力,scaled_attention (batch_size, num_heads, seq_len_q, depth)\n",
        "        # attention_weights (batch_size, num_heads, seq_len_q, seq_len_k)\n",
        "        scaled_attention, attention_weights = self.scaled_dot_product_attention(Q, K, V, mask)\n",
        "\n",
        "        # 合并多头\n",
        "        concat_attention = self.merge_heads(scaled_attention, batch_size)  # (batch_size, seq_len_q, hidden_size)\n",
        "\n",
        "        # 最后的线性层\n",
        "        output = self.Wo(concat_attention)  # (batch_size, seq_len_q, hidden_size)\n",
        "\n",
        "        return AttentionOutput(hidden_states=output, attn_scores=attention_weights)\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 19,
      "id": "970f1a70",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "970f1a70",
        "outputId": "2b90290a-8fa9-4bb5-83db-b7cc780d7722"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "输入张量形状: torch.Size([2, 4, 8])\n",
            "输出张量形状: torch.Size([2, 4, 8])\n",
            "注意力权重形状: torch.Size([2, 2, 4, 4])\n"
          ]
        }
      ],
      "source": [
        "# 验证MultiHeadAttention的正向计算\n",
        "import torch\n",
        "import matplotlib.pyplot as plt\n",
        "\n",
        "# 创建一个简单的测试用例\n",
        "batch_size = 2\n",
        "seq_len = 4\n",
        "hidden_size = 8\n",
        "num_heads = 2\n",
        "\n",
        "# 创建输入张量\n",
        "x = torch.randn(batch_size, seq_len, hidden_size)\n",
        "print(f\"输入张量形状: {x.shape}\")\n",
        "\n",
        "# 创建配置字典\n",
        "config = {\n",
        "    'd_model': hidden_size,\n",
        "    'num_heads': num_heads\n",
        "}\n",
        "\n",
        "# 创建MultiHeadAttention实例\n",
        "mha = MultiHeadAttention(config)\n",
        "\n",
        "# 执行前向传播 (Q=K=V=x，无掩码)\n",
        "output = mha(x, x, x)\n",
        "\n",
        "# 打印结果\n",
        "print(f\"输出张量形状: {output.hidden_states.shape}\")\n",
        "print(f\"注意力权重形状: {output.attn_scores.shape}\")\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 20,
      "id": "f2f28a04",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "f2f28a04",
        "outputId": "210db89b-2e82-401a-8509-f865dc50c36a"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "查询张量形状: torch.Size([2, 4, 8])\n",
            "键值张量形状: torch.Size([2, 6, 8])\n",
            "输出张量形状: torch.Size([2, 4, 8])\n",
            "注意力权重形状: torch.Size([2, 2, 4, 6])\n"
          ]
        }
      ],
      "source": [
        "# 验证MultiHeadAttention做交叉注意力正向计算的没问题的\n",
        "import torch\n",
        "import matplotlib.pyplot as plt\n",
        "\n",
        "# 创建一个简单的测试用例\n",
        "batch_size = 2\n",
        "seq_len_q = 4\n",
        "seq_len_kv = 6  # 不同的序列长度\n",
        "hidden_size = 8\n",
        "num_heads = 2\n",
        "\n",
        "# 创建输入张量\n",
        "q = torch.randn(batch_size, seq_len_q, hidden_size)\n",
        "kv = torch.randn(batch_size, seq_len_kv, hidden_size)\n",
        "print(f\"查询张量形状: {q.shape}\")\n",
        "print(f\"键值张量形状: {kv.shape}\")\n",
        "\n",
        "# 创建配置字典\n",
        "config = {\n",
        "    'd_model': hidden_size,\n",
        "    'num_heads': num_heads\n",
        "}\n",
        "\n",
        "# 创建MultiHeadAttention实例\n",
        "mha = MultiHeadAttention(config)\n",
        "\n",
        "# 执行前向传播 (Q=q, K=V=kv，无掩码)\n",
        "output = mha(q, kv, kv)\n",
        "\n",
        "# 打印结果\n",
        "print(f\"输出张量形状: {output.hidden_states.shape}\")\n",
        "print(f\"注意力权重形状: {output.attn_scores.shape}\")\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "26e43424",
      "metadata": {
        "id": "26e43424"
      },
      "source": [
        "## TransformerBlock"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 21,
      "id": "66324f21",
      "metadata": {
        "id": "66324f21"
      },
      "outputs": [],
      "source": [
        "from dataclasses import dataclass\n",
        "from typing import Optional\n",
        "\n",
        "@dataclass\n",
        "class TransformerBlockOutput:\n",
        "    hidden_states: torch.Tensor\n",
        "    self_attn_scores: torch.Tensor\n",
        "    cross_attn_scores: Optional[torch.Tensor] = None\n",
        "\n",
        "class TransformerBlock(nn.Module):\n",
        "    def __init__(self, config, has_cross_attention=False):\n",
        "        super().__init__()\n",
        "        self.has_cross_attention = has_cross_attention\n",
        "        self.d_model = config['d_model']\n",
        "        self.ffn_dim = config.get('dim_feedforward', 4 * self.d_model)  # 使用配置中的ffn_dim或默认值\n",
        "\n",
        "        # 为不同组件创建独立的dropout层\n",
        "        self.self_attn_dropout = nn.Dropout(config.get('dropout', 0.1))\n",
        "        self.cross_attn_dropout = nn.Dropout(config.get('dropout', 0.1))\n",
        "        self.ffn_dropout = nn.Dropout(config.get('dropout', 0.1))\n",
        "\n",
        "        # 自注意力层\n",
        "        self.self_attention = MultiHeadAttention(config)\n",
        "        # 层归一化\n",
        "        self.self_attn_layer_norm = nn.LayerNorm(self.d_model)\n",
        "\n",
        "        # 交叉注意力层（可选）\n",
        "        if has_cross_attention:\n",
        "            self.cross_attention = MultiHeadAttention(config)\n",
        "            self.cross_attn_layer_norm = nn.LayerNorm(self.d_model)\n",
        "\n",
        "        # 前馈神经网络\n",
        "        self.ffn = nn.Sequential(\n",
        "            nn.Linear(self.d_model, self.ffn_dim),\n",
        "            nn.ReLU(),\n",
        "            # nn.Dropout(config.get('dropout', 0.1)),  # FFN内部的dropout\n",
        "            nn.Linear(self.ffn_dim, self.d_model)\n",
        "        )\n",
        "        self.ffn_layer_norm = nn.LayerNorm(self.d_model)\n",
        "\n",
        "    def forward(self, x, encoder_output=None, self_attn_mask=None, cross_attn_mask=None):\n",
        "        # 自注意力层 + dropout + 残差连接 + LayerNorm\n",
        "        self_attn_output = self.self_attention(x, x, x, self_attn_mask)\n",
        "        x = x + self.self_attn_dropout(self_attn_output.hidden_states)  # 使用专用的self_attn_dropout\n",
        "        x = self.self_attn_layer_norm(x)\n",
        "\n",
        "        self_attn_scores = self_attn_output.attn_scores\n",
        "        cross_attn_scores = None\n",
        "\n",
        "        # 交叉注意力层（如果有） + dropout + 残差连接 + LayerNorm\n",
        "        if self.has_cross_attention and encoder_output is not None:\n",
        "            cross_attn_output = self.cross_attention(x, encoder_output, encoder_output, cross_attn_mask)\n",
        "            x = x + self.cross_attn_dropout(cross_attn_output.hidden_states)  # 使用专用的cross_attn_dropout\n",
        "            x = self.cross_attn_layer_norm(x)\n",
        "            cross_attn_scores = cross_attn_output.attn_scores\n",
        "\n",
        "        # 前馈神经网络 + dropout + 残差连接 + LayerNorm\n",
        "        ffn_output = self.ffn(x)\n",
        "        x = x + self.ffn_dropout(ffn_output)  # 使用专用的ffn_dropout\n",
        "        x = self.ffn_layer_norm(x)\n",
        "\n",
        "        return TransformerBlockOutput(\n",
        "            hidden_states=x,\n",
        "            self_attn_scores=self_attn_scores,\n",
        "            cross_attn_scores=cross_attn_scores\n",
        "        )\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "36a5a199",
      "metadata": {
        "id": "36a5a199"
      },
      "source": [
        "## TransformerEncoder"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 22,
      "id": "081570d2",
      "metadata": {
        "id": "081570d2"
      },
      "outputs": [],
      "source": [
        "from dataclasses import dataclass\n",
        "from typing import List\n",
        "\n",
        "import torch\n",
        "from torch import Tensor\n",
        "import torch.nn as nn\n",
        "\n",
        "@dataclass\n",
        "class TransformerEncoderOutput:\n",
        "    last_hidden_states: Tensor\n",
        "    attn_scores: List[Tensor]\n",
        "\n",
        "class TransformerEncoder(nn.Module):\n",
        "    def __init__(self, config):\n",
        "        super().__init__()\n",
        "        self.num_layers = config.get('encoder_layers', 6)\n",
        "\n",
        "        # 创建多层Transformer编码器块\n",
        "        self.layers = nn.ModuleList([\n",
        "            TransformerBlock(config, has_cross_attention=False)\n",
        "            for _ in range(self.num_layers)\n",
        "        ])\n",
        "\n",
        "    def forward(self, x, attention_mask=None):\n",
        "        # 用于收集所有层的注意力分数\n",
        "        all_attn_scores = []\n",
        "\n",
        "        # 依次通过每个编码器层\n",
        "        for layer in self.layers:\n",
        "            output = layer(x, self_attn_mask=attention_mask)\n",
        "            x = output.hidden_states\n",
        "            all_attn_scores.append(output.self_attn_scores)\n",
        "\n",
        "        return TransformerEncoderOutput(\n",
        "            last_hidden_states=x,\n",
        "            attn_scores=all_attn_scores\n",
        "        )\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 23,
      "id": "abe12b93",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "abe12b93",
        "outputId": "448a71dc-060b-4d71-d50d-5bf4ab5ae8aa"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "tensor([[[[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]],\n",
            "\n",
            "\n",
            "        [[[0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1]]]])\n",
            "输出张量形状: torch.Size([2, 12, 64])\n",
            "注意力层数: 2\n",
            "第一层注意力分数形状: torch.Size([2, 4, 12, 12])\n",
            "第一层第二个样本的注意力分数，第9个位置是否接近0: False\n"
          ]
        }
      ],
      "source": [
        "def test_transformer_encoder():\n",
        "    # 创建一个简单的配置\n",
        "    config = {\n",
        "        'encoder_layers': 2,\n",
        "        'd_model': 64,\n",
        "        'num_heads': 4,\n",
        "        'dim_feedforward': 128,\n",
        "        'dropout': 0.1,\n",
        "        'max_length': 100,\n",
        "        'vocab_size': vocab_size,\n",
        "        'pad_idx': 0,\n",
        "    }\n",
        "\n",
        "    # 实例化模型\n",
        "    encoder = TransformerEncoder(config)\n",
        "\n",
        "    # 生成一个批次的输入\n",
        "    batch_size = 2\n",
        "    hidden_size = config['d_model']\n",
        "\n",
        "    inputs_words = [\"The quick brown fox jumps over the lazy dog .\", \"What does the fox say ?\"]\n",
        "\n",
        "    #encode变为id\n",
        "    # 使用tokenizer将文本编码为token IDs\n",
        "    src_sequence, src_padding_mask = tokenizer.encode([w.split() for w in inputs_words], return_mask=True)\n",
        "    # 通过TransformerEmbedding处理输入序列\n",
        "    src_embedded = TransformerEmbedding(config)(src_sequence)\n",
        "    print(src_padding_mask.unsqueeze(1).unsqueeze(2))\n",
        "\n",
        "    # 执行前向传播\n",
        "    output = encoder(src_embedded, src_padding_mask.unsqueeze(1).unsqueeze(2))\n",
        "\n",
        "    # 验证输出形状\n",
        "    print(f\"输出张量形状: {output.last_hidden_states.shape}\")\n",
        "    print(f\"注意力层数: {len(output.attn_scores)}\")\n",
        "    print(f\"第一层注意力分数形状: {output.attn_scores[0].shape}\")\n",
        "\n",
        "    # 检查注意力掩码是否正常工作\n",
        "    # 对于被掩盖的位置，注意力分数应该很小\n",
        "    print(f\"第一层第二个样本的注意力分数，第9个位置是否接近0: {output.attn_scores[0][1, :, 8:].mean().item() < 0.01}\")\n",
        "\n",
        "    return output\n",
        "\n",
        "# 运行测试\n",
        "test_output = test_transformer_encoder()\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "97a1b24f",
      "metadata": {
        "id": "97a1b24f"
      },
      "source": [
        "## TransformerDecoder"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 24,
      "id": "eebcf9f5",
      "metadata": {
        "id": "eebcf9f5"
      },
      "outputs": [],
      "source": [
        "from dataclasses import dataclass\n",
        "from typing import List\n",
        "\n",
        "@dataclass\n",
        "class TransformerDecoderOutput:\n",
        "    last_hidden_states: torch.Tensor\n",
        "    self_attn_scores: List[torch.Tensor]\n",
        "    cross_attn_scores: List[torch.Tensor]\n",
        "\n",
        "class TransformerDecoder(nn.Module):\n",
        "    def __init__(self, config):\n",
        "        super().__init__()\n",
        "        self.layers = nn.ModuleList([\n",
        "            TransformerBlock(\n",
        "                config,\n",
        "                has_cross_attention=True\n",
        "            )\n",
        "            for _ in range(config['num_decoder_layers'])\n",
        "        ])\n",
        "        self.dropout = nn.Dropout(config['dropout'])\n",
        "\n",
        "    def forward(self, x, encoder_output, self_attn_mask=None, cross_attn_mask=None):\n",
        "        self_attn_scores = [] # 存储每个层的自注意力分数\n",
        "        cross_attn_scores = [] # 存储每个层的交叉注意力分数\n",
        "\n",
        "        for layer in self.layers:\n",
        "            layer_output = layer(\n",
        "                x,\n",
        "                encoder_output,\n",
        "                self_attn_mask,\n",
        "                cross_attn_mask\n",
        "            )\n",
        "\n",
        "            x = layer_output.hidden_states\n",
        "            self_attn_scores.append(layer_output.self_attn_scores)\n",
        "            cross_attn_scores.append(layer_output.cross_attn_scores)\n",
        "\n",
        "        return TransformerDecoderOutput(\n",
        "            last_hidden_states=x,\n",
        "            self_attn_scores=self_attn_scores,\n",
        "            cross_attn_scores=cross_attn_scores\n",
        "        )\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "e1e476f2",
      "metadata": {
        "id": "e1e476f2"
      },
      "source": [
        "## 生成look ahead mask"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 25,
      "id": "8254102c",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "8254102c",
        "outputId": "961d2c77-2d52-4ead-de5f-7fa840bc8346"
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "tensor([[False,  True,  True,  True,  True],\n",
              "        [False, False,  True,  True,  True],\n",
              "        [False, False, False,  True,  True],\n",
              "        [False, False, False, False,  True],\n",
              "        [False, False, False, False, False]])"
            ]
          },
          "execution_count": 25,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "(torch.triu(torch.ones(5, 5))==0).transpose(-1, -2)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 26,
      "id": "1db53d89",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 634
        },
        "id": "1db53d89",
        "outputId": "760aae68-547a-4053-ce55-67cb32170e4b"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Look-ahead mask for size 3:\n",
            "tensor([[False,  True,  True],\n",
            "        [False, False,  True],\n",
            "        [False, False, False]])\n",
            "\n",
            "Look-ahead mask for size 5:\n",
            "tensor([[False,  True,  True,  True,  True],\n",
            "        [False, False,  True,  True,  True],\n",
            "        [False, False, False,  True,  True],\n",
            "        [False, False, False, False,  True],\n",
            "        [False, False, False, False, False]])\n"
          ]
        },
        {
          "data": {
            "image/png": "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",
            "text/plain": [
              "<Figure size 480x480 with 2 Axes>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "def generate_look_ahead_mask(size):\n",
        "    \"\"\"\n",
        "    生成上三角掩码(look-ahead mask)，用于Transformer解码器中的自注意力机制\n",
        "\n",
        "    Args:\n",
        "        size (int): 掩码的大小 (size x size)\n",
        "\n",
        "    Returns:\n",
        "        torch.Tensor: 布尔类型的上三角掩码，其中True表示被掩盖的位置\n",
        "    \"\"\"\n",
        "    # 创建上三角矩阵(1s在上三角，包括对角线；0s在下三角)\n",
        "    mask = torch.triu(torch.ones(size, size), diagonal=1).bool()\n",
        "\n",
        "    # 在解码器的自注意力中，我们通常掩盖未来的位置(右上方)\n",
        "    # 所以需要转置使得右上方为True(被掩盖)\n",
        "    return mask\n",
        "\n",
        "# 测试不同大小的look-ahead mask\n",
        "print(\"Look-ahead mask for size 3:\")\n",
        "print(generate_look_ahead_mask(3))\n",
        "print(\"\\nLook-ahead mask for size 5:\")\n",
        "print(generate_look_ahead_mask(5))\n",
        "plt.matshow(generate_look_ahead_mask(16))\n",
        "plt.colorbar()\n",
        "plt.xlabel(\"keys\")\n",
        "plt.ylabel(\"querys\")\n",
        "plt.title(\"1 means mask while 0 means unmask\")\n",
        "plt.show()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 27,
      "id": "a473db90",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 967
        },
        "id": "a473db90",
        "outputId": "dab9abaf-4e5e-47f6-831a-0107de0e5109"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "['[BOS]', '[UNK]', 'quick', 'brown', 'fox', '[UNK]', 'over', 'the', 'lazy', 'dog', '.', '[EOS]']\n"
          ]
        },
        {
          "data": {
            "image/png": "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emJvuLSTwIAgd28OAPiVZCtJomSFOS8oJCTE3ZvjMYhNyEmrYqPdvQmA14hPSJEilY5lKi555REpAAAAAHAnEikAAAAAsIlECgAAAABsIpECAAAAAJtIpAAAAADAJhIpAAAAALCJRAoAAAAAbCKRAgAAAACbSKQAAAAAwKZAu08AAACA92hdupbLy1wVG+3yMgFX44gUAAAAANhEIgUAAAAANpFIAQAAAIBNJFIAAAAAYBOJFAAAAADYRCIFAAAAADaRSAEAAACATSRSAAAAAOCKRComJkZOnTrlvL9jxw4ZPHiwzJw5MyurAwAgW4hLAACvSKS6du0q69evN7fPnDkjLVu2NEFr5MiRMnbs2JzeRgAAboi4BADwikTqwIEDcv/995vbS5culerVq8vWrVtlwYIFMnfu3JzeRgAAboi4BADwikQqKSlJgoODze21a9fKY489Zm7fc8898ssvv+TsFgIAcBPEJQCAVyRS1apVk+nTp8umTZtkzZo10qZNGzM/NjZWihUrZmtdUVFREhYWZvqx161bN81jjvu9evWStm3bXjNfnzts2DBze9u2bdKwYUO5ePGi9OjRQ8qUKZOVXQMAeKGcjEuK2AQAyJVEauLEiTJjxgwJDw+XJ598Uu69914zf+XKlc6uFXZ07txZ+vXrd8Nl9CTiffv2ZfjY/v37ZdCgQbJs2TIpXLiwzJs3T0qWLJnhsomJiRIfH59mAgB4t5yOS4rYBAC4kUDJAg1U586dMxV9kSJFnPM14Nx6662SG7R1b9KkSTJ//vw0848fPy69e/eWTz/9VEqUKHHT9URGRsqYMWNyZRsBAO7hjrikiE0A4L+ydERq9OjRphUudbBSd999t9x+++2SG+rUqWOC5MmTJ9PMX7dundSvX9+UnRkRERESFxfnnHTIXACAd3NHXFLEJgDwX1lKpFasWCHly5eX5s2by8KFC02XhJwQEBDgvH358mXJnz9/mseHDh0qU6ZMSTNPW/xOnz4tH330UabK0JORQ0JC0kwAAO+WW3FJEZsAADmWSEVHR8vOnTvNyb3a/1v7fPfv39/My46yZcuadavNmzdLjRo10jyu1wXZs2ePnD9//n87kCePGd529uzZsnr16myVDwDwTrkVlxSxCQCQY+dIqdq1a5tJW+G++OILmTNnjhmZSIea7dOnjxnNKDQ01NY6x48f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",
            "text/plain": [
              "<Figure size 1000x500 with 2 Axes>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "--------------------------------------------------\n",
            "['[BOS]', '[UNK]', 'does', 'the', 'fox', 'say', '?', '[EOS]', '[PAD]', '[PAD]', '[PAD]', '[PAD]']\n"
          ]
        },
        {
          "data": {
            "image/png": "iVBORw0KGgoAAAANSUhEUgAAA1AAAAG1CAYAAAD3DRUpAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjAsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvlHJYcgAAAAlwSFlzAAAPYQAAD2EBqD+naQAAQIlJREFUeJzt3Qd4FOX2+PGTEAg1AcVCTCx0UQSk/kEggDRb6AgoIFxQQAUFLvJwEQU1IiogFkCvYEGQZgMx9A6C0uQKSBMSAogXTCIllMz/Oe99dn9JCGQSNruz2e/neQZ2Z2fnndlk5+S8c+adIMuyLAEAAAAAZCs4+0UAAAAAAIoECgAAAABsIoECAAAAAJtIoAAAAADAJhIoAAAAALCJBAoAAAAAbCKBAgAAAACbSKAAAAAAwCYSKAAAAACwiQQKyML06dMlKChIfv/99wzzx40bJ2XLlpUCBQpI9erVfbZ9+d1LL71kPv8///zT15sCALZjhKf07NlTihcvLt7en59++kmcFgf8FXEsfyOBAmxavHix/POf/5QGDRrItGnT5LXXXvPo+tevX28OuH/99ddlr2lbX3/9tUfbAwAAQM6RQAE2LV++XIKDg+Xf//63dO/eXR544AGPJ1Avv/wyCRQAAICDkUABNv3xxx9SpEgRKVSokK83BQAAAD5CAoV8JSUlRQYNGiS33367hIaGyo033ijNmzeXLVu2uJf58ccfpVWrVhIeHi5FixaVxo0by7p16666Xq1j1rK906dPm8c6ac24HTt27DD17HrtVOHCheXmm2+WXr16yX//+1/3Mlq6N3ToUPP4jjvucLeh9fX6v7b7ySefuOfr+lzv0+f79u0z80qWLGn264knnpAzZ87kqub+8OHD8tBDD5nHt9xyi7z33nvm9V9++UWaNm0qxYoVk9tuu02++OKLDO8/efKkDBkyRKpWrWreGxYWJq1bt5bt27df1takSZPkrrvuMp9/qVKlpFatWpetL7NDhw5J+fLl5e6775bjx4/naN8AIK+9//775rimsSciIkIGDBiQZUXBnDlzpGbNmqZDrnTp0vLYY4/JkSNHsl3/tm3b5IYbbpDo6Gj5+++/bW2THjf79+8vlSpVMu1df/310rFjxyteu5WamirPP/+8aUeP9W3btpUTJ05cttyiRYukYcOGZpkSJUrIgw8+KP/5z39yHPtc1q5dK7Vr1zbLlStXTqZMmSK5QRyDt4R4rSXAC5566imZO3euPP3001KlShVzoNYD865du+Tee+81ZXh6MNTgNWrUKFOSp4mRHlDXrFkjderUyXK9n332mUydOlU2bdokH330kZlXv359W9u0ZMkSOXDggElqNIBokNF16f8bN240CVC7du3kt99+k5kzZ8r48eNNUFUaxLTtf/zjH2bb+vbta+ZrgEmvU6dOJvGKjY01yaJuoyaPY8eOzdHnd+nSJfP5NGrUSN544w2ZMWOG+Sw12IwYMUK6detmtnXy5MmmjPH//b//Z9pVuo9aZqjBWedpcNAgqAnqr7/+av6gUB9++KE8++yz0qFDBxk4cKCcO3fOBFpNbLt27Zrldu3fv9/8jK677jrzebo+HwBwAu3M0hLs+++/X/r16yd79uyRDz74QDZv3mw66AoWLGiW0443jQWaLOjxWo+TEydONMts3brVdIJlRdfTsmVL80f6N998Y5IhO/R9Wh7+6KOPSmRkpEmcdLs0CdPjsv7xn94zzzxjkgGNj7rshAkTTAz48ssv3ctoTOrRo4fZHo0x2lmn67zvvvvMPmgHpt3Y50pqWrRoYeKdfo4XL1407d900025+lkQx+AVFpCPhIeHWwMGDMjytbS0NKtChQpWy5YtzWOXM2fOWHfccYfVvHlz97xp06ZZ+vU4ePCge16PHj2sYsWK5XibdP2ZzZw506x/9erV7nnjxo27rE0XbVfbz2zUqFHmPb169cowv23bttb111+fo+3U9eu6XnvtNfe8U6dOWUWKFLGCgoKsWbNmuefv3r3bLKvtu5w7d866dOlShnXqvoSGhlqjR492z4uJibHuuuuuq26La79OnDhh7dq1y4qIiLBq165tnTx5Mkf7BAB5IX2M+OOPP6xChQpZLVq0yHAMfPfdd80yH3/8sXl+/vx568Ybb7Tuvvtu6+zZs+7lFixYYJZ78cUXs4w3a9eutcLCwqwHH3zQHGevNf5s2LDBtPfpp59etj/3339/hvj43HPPWQUKFLD++usv8zwlJcUqWbKk1adPnwzrPHbsmIm/6efbjX1t2rSxChcubB06dMg979dffzXt5vTPVOIYvIUSPuQr2nunPUCJiYlZlj/s3bvX9A7pmSkdWlQnLY9r1qyZrF69WtLS0jy+Tel7CrWXStusV6+eeZ6+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Abn066+/SmJi4lWX8db9pvLDdgIA7Dlw4ICZrua+++7LcD8if0Ycg9OQQAEAAACATQwiAQAAAAA2kUABAAAAgE0kUHDbuXOnuVDTm37//Xdzd3JVq1Ytr7WrlasxMTHSpEkTOXHihASSH3/80dw9Xe8ir3dGBwCn8kVc8lVsCuS4pIhN8CckUOmsXLlSoqKiZOrUqRIdHS0NGzaURo0aSdeuXeXSpUtmmV9++UWaNWsmjRs3loceekji4+PN/B07dphldX79+vXlyJEj5qLH6tWry5AhQ2y1mfkg7XquwaN169aXzdf3uta9YcMGc+D566+/pHv37hIZGSn+IH2Q8qZjx46Z/1esWGGGeg0kZcqUkeXLl8v69etl4sSJefK90f910qFn09LS5F//+peZrxc1v/POO+736u+v/t7q/DFjxph5//znP6VkyZJXHaI3qzbr1KnjXofS7+Ho0aPdz6dPny4VKlSQpk2bmuWnTJnifq1Fixa2/kjyRbuB0iaujNgUGLEpkOOSIjYRm2o5sM0r0kEk8D8rVqywBg8ebB43btzYSklJMY/79OljrVmzxjp//rx1zz33WPv27TPz165dazVq1Mg87tChg7Vz507z+MyZM9bZs2cvW2d2bdasWTPDa67nPXr0sO6++25r+/btGea73rtjxw6rdu3a1rFjxy57b3YuXLhgdezY0WrWrJnVq1cv09bMmTOtOnXqWHXr1rV++OEHs9zmzZut6Oho67777rPGjRtn5n3wwQem3SZNmljz58+3cqNTp05WZGSk+bwrV65sde/e3apWrZr1+eefm9f3799vtWjRwrw+aNAgy1N0n0uXLm21adPG6tatm/k5PvDAA9bJkyetqVOnWi+99JKVlpZmtWzZ0vr111890uaGDRvM56qf46hRo6znnnvOtKuf4datW60//vjDbINL06ZNraSkJCuvrFq1yux7Xn1vXPTz7Nevn/v3TfdxyZIl5vui3xsX/exdslpPdm3quvX7GR8fbx0+fNj8jPV302XatGnWpEmTzOPTp0+b36sFCxbk6Dvji3YDpU1cWaDFJl/HJV/FJuLS/xCbiE3+EJs4A2VDSkqKhIWFycaNG02vXbly5cx87Z3QHgzt6StSpIgsXbpUTp8+bR57euhQ7Q154403srzPQ69evWT27Nly00035Xi9X3/9tZQvX95s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",
            "text/plain": [
              "<Figure size 1000x500 with 2 Axes>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "--------------------------------------------------\n"
          ]
        }
      ],
      "source": [
        "inputs_words = [\"The quick brown fox jumps over the lazy dog .\", \"What does the fox say ?\"]\n",
        "\n",
        "#encode变为id\n",
        "inputs_ids, input_padding_mask = tokenizer.encode([w.split() for w in inputs_words], return_mask=True)\n",
        "for i in range(len(inputs_words)):\n",
        "    decode_text = tokenizer.decode(inputs_ids[i: i+1].tolist(), remove_bos=False, remove_eos=False, remove_pad=False, split=True)[0]\n",
        "    print(decode_text)\n",
        "    # print(input_padding_mask[i].reshape(1, -1))\n",
        "    #repeat_interleave作用：将input_padding_mask[i]重复inputs_ids.shape[-1]次，dim=0表示在第0维度上重复\n",
        "    self_attn_mask  = input_padding_mask[i].reshape(1, -1).repeat_interleave(inputs_ids.shape[-1], dim=0)\n",
        "    # print(input_mask[i].reshape(1, -1).repeat_interleave(inputs_ids.shape[-1], dim=0))\n",
        "    look_ahead_mask = generate_look_ahead_mask(inputs_ids.shape[-1])\n",
        "\n",
        "    fig, axs = plt.subplots(1, 2, figsize=(10, 5))\n",
        "    axs[0].matshow(self_attn_mask)\n",
        "    axs[0].set_title(\"self_attn_mask\")\n",
        "    axs[0].set_yticks(range(len(decode_text)), decode_text, fontsize=6)\n",
        "    axs[0].set_ylabel(\"querys\")\n",
        "    axs[0].set_xticks(range(len(decode_text)), decode_text, fontsize=6)\n",
        "    axs[0].set_xlabel(\"keys\")\n",
        "    axs[1].matshow(look_ahead_mask)\n",
        "    axs[1].set_title(\"look_ahead_mask\")\n",
        "    axs[1].set_yticks(range(len(decode_text)), decode_text, fontsize=6)\n",
        "    axs[1].set_ylabel(\"querys\")\n",
        "    axs[1].set_xticks(range(len(decode_text)), decode_text, fontsize=6)\n",
        "    axs[1].set_xlabel(\"keys\")\n",
        "    plt.show()\n",
        "    print('-'*50)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "84f2a6c9",
      "metadata": {
        "id": "84f2a6c9"
      },
      "source": [
        "## TransformerModel"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 28,
      "id": "59fa00df",
      "metadata": {
        "id": "59fa00df"
      },
      "outputs": [],
      "source": [
        "from dataclasses import dataclass\n",
        "from typing import Optional, List, Dict, Any, Tuple\n",
        "import torch\n",
        "import torch.nn as nn\n",
        "import torch.nn.functional as F\n",
        "import math\n",
        "import numpy as np\n",
        "import time\n",
        "\n",
        "\n",
        "@dataclass\n",
        "class TransformerOutput:\n",
        "    logits: torch.Tensor\n",
        "    encoder_attentions: Optional[List[torch.Tensor]] = None\n",
        "    decoder_attentions: Optional[List[torch.Tensor]] = None\n",
        "    cross_attentions: Optional[List[torch.Tensor]] = None\n",
        "    preds: Optional[torch.Tensor] = None\n",
        "\n",
        "\n",
        "class TransformerModel(nn.Module):\n",
        "    def __init__(self, config: Dict[str, Any]):\n",
        "        super().__init__()\n",
        "        self.d_model = config.get(\"d_model\", 512)\n",
        "        self.num_heads = config.get(\"num_heads\", 8)\n",
        "        self.pad_token_id = config.get(\"pad_token_id\", 0)\n",
        "        self.pad_idx = config.get(\"pad_idx\", 0)\n",
        "        self.vocab_size = config.get(\"vocab_size\")\n",
        "        self.share_embeddings = config.get(\"share_embeddings\", False)\n",
        "        self.max_length=config['max_length']\n",
        "        self.bos_idx = config[\"bos_idx\"]\n",
        "        self.eos_idx = config[\"eos_idx\"]\n",
        "        # Embedding layers using TransformerEmbedding\n",
        "        self.src_embedding = TransformerEmbedding(config=config)\n",
        "\n",
        "        if self.share_embeddings:\n",
        "            self.tgt_embedding = self.src_embedding\n",
        "            # Share embedding weights with output projection layer\n",
        "            self.output_projection = lambda x: torch.matmul(\n",
        "                x, self.tgt_embedding.get_word_embedding_weights().T\n",
        "            )  # 输出层，共享参数，直接拿原有embedding矩阵的转置，节省内存\n",
        "        else:\n",
        "            self.tgt_embedding = TransformerEmbedding(config=config)\n",
        "            self.output_projection = nn.Linear(self.d_model, self.vocab_size)\n",
        "\n",
        "        # Encoder and Decoder\n",
        "        self.encoder = TransformerEncoder(config=config)\n",
        "\n",
        "        self.decoder = TransformerDecoder(config=config)\n",
        "\n",
        "        # Initialize parameters with Xavier uniform\n",
        "        self._init_parameters()\n",
        "\n",
        "    def _init_parameters(self):\n",
        "        for p in self.parameters():\n",
        "            if p.dim() > 1:\n",
        "                nn.init.xavier_uniform_(p)\n",
        "\n",
        "    def forward(\n",
        "        self,\n",
        "        src_inputs: torch.Tensor,\n",
        "        tgt_inputs: torch.Tensor,\n",
        "        src_padding_mask: Optional[torch.Tensor] = None,\n",
        "        tgt_padding_mask: Optional[torch.Tensor] = None,\n",
        "    ) -> TransformerOutput:\n",
        "        batch_size, src_seq_len = src_inputs.size()\n",
        "        bs, tgt_seq_len = tgt_inputs.size()\n",
        "\n",
        "        # Create masks if not provided，实际是一定会传的，shape从[batch_size,src_seq_len]变为[batch_size,1,1,src_seq_len]\n",
        "        src_padding_mask = src_padding_mask.unsqueeze(1).unsqueeze(2)\n",
        "\n",
        "        if tgt_padding_mask is None:\n",
        "            tgt_padding_mask = tgt_inputs == self.pad_token_id\n",
        "\n",
        "        # Create look-ahead mask for decoder\n",
        "        look_ahead_mask = generate_look_ahead_mask(tgt_seq_len).to(tgt_inputs.device)\n",
        "\n",
        "        # print(f\"tgt_padding_mask.shape:{tgt_padding_mask.shape}\")\n",
        "        # 合并decoder_inputs的padding_mask和look_ahead_mask,shape变为[batch_size,tgt_seq_len,tgt_seq_len]\n",
        "        combined_mask = torch.max(\n",
        "            tgt_padding_mask.unsqueeze(1).repeat(1, tgt_seq_len, 1), look_ahead_mask\n",
        "        )\n",
        "        combined_mask = combined_mask.unsqueeze(\n",
        "            1\n",
        "        )  # 变为[batch_size, 1, tgt_seq_len, tgt_seq_len]\n",
        "        # print(f\"combined_mask.shape:{combined_mask.shape}\")\n",
        "\n",
        "        # Embeddings\n",
        "        src_embedded = self.src_embedding(src_inputs)\n",
        "        tgt_embedded = self.tgt_embedding(tgt_inputs)\n",
        "\n",
        "        # 编码器模块计算\n",
        "        encoder_output = self.encoder(src_embedded, attention_mask=src_padding_mask)\n",
        "        # print(f\"src_padding_mask.shape:{src_padding_mask.shape}\")\n",
        "        # print(f\"combined_mask.shape:{combined_mask.shape}\")\n",
        "        # 解码器模块计算\n",
        "        decoder_output = self.decoder(\n",
        "            tgt_embedded,\n",
        "            encoder_output.last_hidden_states,\n",
        "            self_attn_mask=combined_mask,\n",
        "            cross_attn_mask=src_padding_mask,  # 交叉注意力mask\n",
        "        )\n",
        "\n",
        "        # 分类层\n",
        "        logits = self.output_projection(decoder_output.last_hidden_states)\n",
        "\n",
        "        return TransformerOutput(\n",
        "            logits=logits,\n",
        "            encoder_attentions=encoder_output.attn_scores,\n",
        "            decoder_attentions=decoder_output.self_attn_scores,\n",
        "            cross_attentions=decoder_output.cross_attn_scores,\n",
        "        )\n",
        "\n",
        "    @torch.no_grad()\n",
        "    def infer(self, encoder_inputs, encoder_inputs_mask=None):\n",
        "        if encoder_inputs_mask is None:  # 应对多个样本同时进行推理\n",
        "            encoder_inputs_mask = encoder_inputs.eq(self.pad_idx)\n",
        "        encoder_inputs_mask = encoder_inputs_mask.unsqueeze(1).unsqueeze(\n",
        "            2\n",
        "        )  # [batch_size, 1, 1, src_len],[1,src_len]相加时，会自动广播到[batch_size,1,src_len,src_len]\n",
        "        look_ahead_mask = generate_look_ahead_mask(self.max_length)\n",
        "        look_ahead_mask = (\n",
        "            look_ahead_mask.unsqueeze(0).unsqueeze(0).to(encoder_inputs.device)\n",
        "        )  # [1, 1, trg_len, trg_len]\n",
        "\n",
        "        # 做embedding\n",
        "        encoder_inputs_embeds = self.src_embedding(encoder_inputs)\n",
        "        encoder_outputs = self.encoder(\n",
        "            encoder_inputs_embeds,\n",
        "            encoder_inputs_mask\n",
        "        )\n",
        "        # 解码器模块计算\n",
        "        decoder_inputs = torch.Tensor([self.bos_idx] * encoder_inputs.shape[0]).reshape(-1, 1).long().to(device=encoder_inputs.device)\n",
        "        for cur_len in tqdm(range(1, self.max_length + 1)):\n",
        "            # 做decoder的embedding\n",
        "            decoder_inputs_embeds = self.tgt_embedding(decoder_inputs)\n",
        "            decoder_outputs = self.decoder(\n",
        "                decoder_inputs_embeds,\n",
        "                encoder_outputs.last_hidden_states,\n",
        "                look_ahead_mask[:, :, :cur_len, :cur_len],#decoder的自注意力mask\n",
        "                encoder_inputs_mask\n",
        "            )\n",
        "\n",
        "            logits = self.output_projection(decoder_outputs.last_hidden_states)  # (batch_size, trg_len, vocab_size)\n",
        "            next_token = logits.argmax(dim=-1)[:, -1:] #通过最大下标确定类别，[:, -1:]表示取最后一个结果\n",
        "            decoder_inputs = torch.cat([decoder_inputs, next_token], dim=-1) #预测输出拼接到输入中\n",
        "            #(decoder_inputs == self.eos_idx).sum(dim=-1)是判断样本中是否含有EOS标记\n",
        "            #all是每一个都为True，才会结束\n",
        "            if all((decoder_inputs == self.eos_idx).sum(dim=-1) > 0):\n",
        "                break\n",
        "        return TransformerOutput(\n",
        "            preds=decoder_inputs[:, 1:],\n",
        "            logits=logits,\n",
        "            encoder_attentions=encoder_outputs.attn_scores,\n",
        "            decoder_attentions=decoder_outputs.self_attn_scores,\n",
        "            cross_attentions=decoder_outputs.cross_attn_scores,\n",
        "        )"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a8469135",
      "metadata": {
        "id": "a8469135"
      },
      "source": [
        "# 损失函数"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 29,
      "id": "307583eb",
      "metadata": {
        "id": "307583eb"
      },
      "outputs": [],
      "source": [
        "class CrossEntropyWithPadding:\n",
        "    def __init__(self, config):\n",
        "        self.label_smoothing = config[\"label_smoothing\"]\n",
        "\n",
        "    def __call__(self, logits, labels, padding_mask=None):\n",
        "        # logits.shape = [batch size, sequence length, num of classes]\n",
        "        # labels.shape = [batch size, sequence length]\n",
        "        # padding_mask.shape = [batch size, sequence length]，decode_label_mask\n",
        "        bs, seq_len, nc = logits.shape\n",
        "        loss = F.cross_entropy(logits.reshape(bs * seq_len, nc), labels.reshape(-1), reduce=False, label_smoothing=self.label_smoothing) #label_smoothing表示随机将一个类别的概率设置为0.1，使得模型更加关注其他类别\n",
        "        if padding_mask is None:\n",
        "            loss = loss.mean()\n",
        "        else:\n",
        "            padding_mask = 1 - padding_mask.reshape(-1) #将padding_mask reshape成一维张量，mask部分为0，非mask部分为1\n",
        "            loss = torch.mul(loss, padding_mask).sum() / padding_mask.sum()\n",
        "\n",
        "        return loss\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 30,
      "id": "d85aeade",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 449
        },
        "id": "d85aeade",
        "outputId": "c8382f4b-13fa-4713-aba1-81ceb522211e"
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "[<matplotlib.lines.Line2D at 0x178ce46c290>]"
            ]
          },
          "execution_count": 30,
          "metadata": {},
          "output_type": "execute_result"
        },
        {
          "data": {
            "image/png": "iVBORw0KGgoAAAANSUhEUgAAAiwAAAGdCAYAAAAxCSikAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjAsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvlHJYcgAAAAlwSFlzAAAPYQAAD2EBqD+naQAAS3RJREFUeJzt3QlYlVX+B/Av+w4qKCigSKCoIIuI+1I6UVppmgs6aY7/mso1y1JTmZYJSy0XGB2bmZolxDQ1M7MMtVxTWVRwX0GUTWSX7d77f85xYEBRAYH3Lt/P89z0vPfcyzm99/r+OL9zzmuk0Wg0ICIiItJixko3gIiIiOhhGLAQERGR1mPAQkRERFqPAQsRERFpPQYsREREpPUYsBAREZHWY8BCREREWo8BCxEREWk9U+gJtVqN69evw87ODkZGRko3h4iIiOpA7F9bUFCAdu3awdjYWP8DFhGsuLu7K90MIiIiaoDU1FS4ubnpf8AiRlYqO2xvb690c4iIiKgO8vPz5YBD5XVc7wOWyjSQCFYYsBAREemWh03n4KRbIiIi0noMWIiIiEjrMWAhIiIirceAhYiIiLQeAxYiIiLSz4AlKioKHh4esLS0RK9evXDkyJH71k1OTsbo0aNlfTEDeMWKFbXWS0tLw+9//3s4OjrCysoKfn5+OHbsWEOaR0RERIYesGzYsAFz5sxBeHg44uPj4e/vj9DQUGRmZtZav7i4GJ6enliyZAlcXFxqrXPr1i3069cPZmZm+OGHH3Dq1CksX74cLVu2rH+PiIiISO8YacSeuPUgRlR69uyJyMjIqi3xxYYvM2bMwLx58x74WjHKMnv2bPmoTrzuwIED2LdvHx5l4xkHBwfk5eVxHxYiIiIdUdfrd71GWMrKyhAXF4ehQ4f+7w2MjWX50KFDDW7stm3bEBwcjDFjxqBNmzYIDAzE559//sDXlJaWyk5WfxAREZF+qlfAkp2dDZVKBWdn5xrHRTk9Pb3Bjbh06RLWrFkDb29v/Pjjj3jttdcwc+ZM/POf/7zvayIiImREVvngfYSIiIj0l1asEhJppaCgIHz00UdydOWVV17Byy+/jLVr1973NfPnz5fDR5UPcQ8hIiIi0k/1ClicnJxgYmKCjIyMGsdF+X4Tauuibdu26Nq1a41jXbp0QUpKyn1fY2FhUXXfIN4/iIiISL/VK2AxNzdHjx49EBsbW2N0RJT79OnT4EaIFUJnz56tcezcuXPo0KFDg9+TiIiIHp1Ym/PvQ1ewYMtJKKned2sWS5onT54sJ8mGhITIfVWKioowZcoU+fykSZPg6uoq55hUTtQVy5Qr/y72W0lMTIStrS28vLzk8TfeeAN9+/aVKaGxY8fKfV3WrVsnH0RERKSM/JJyzPvmBHacvDNP9WlfFwzwbq0by5oFsaR56dKlcqJtQEAAVq1aJZc7C4MHD5bLl7/88ktZvnLlCjp27HjPewwaNAh79+6tKm/fvl3OSzl//rysLwIjMY+lrrismYiIqPGcuJaLadHxSM25DTMTI7zzlA+m9u8oN4FtTHW9fjcoYNFGDFiIiIgenQgLvjhwBRE/nEa5SgO3llaInBCEAPcWUPL6Xe+UEBEREemn3OIyzN10ArtO3Vlc81Q3F3z8Qnc4WJkp3TQGLERERATEp9zCjOgEpOXehrmJMd4d3gWT+nRo9BRQQzFgISIiMmBqtQZ/238Jn+w8iwq1Bh0crRE1IQi+rg7QJgxYiIiIDFROURne2ngcu8/cuYHxM93bImKUH+wslU8B3Y0BCxERkQE6eiUHM9cn4EZeCcxNjRH+bFdMCGmvNSmguzFgISIiMrAU0JpfLuLTXeegUmvg6WQjVwF1bafdK2wZsBARERmI7MJSvLEhEfvOZ8vy84Gu+HCkL2wstD8c0P4WEhER0SM7dPEmZsUkILOgFJZmxnj/OV+MCXbT2hTQ3RiwEBER6TGVWoPI3RewMvYc1BrAu40toiYGoZOzHXQJAxYiIiI9lVlQgtkxiTh48aYsj+nhhvdGdIO1ue5d/nWvxURERPRQ+89nY/aGRDlvxdrcRM5VGRXkBl3FgIWIiEiPVKjUWBl7HpF7LkDcLdDHxU6uAvJqYwtdxoCFiIhIT6TnlWBmTAKOXM6R5bCQ9nJ/FUszE+g6BixERER6YO/ZTMz5+rjcvdbG3AQRo7vjOf920BcMWIiIiHRYuUqN5T+dw9pfLspy17b2chVQRycb6BMGLERERDrqeu5tzFifgLirt2RZ3F15wbAuepECuhsDFiIiIh3086kMvLXpOHKLy2FnYYqPX+iOYX5toa8YsBAREemQsgo1Ptl5Bn/bf1mWu7s5IDIsCO0draHPGLAQERHpiNScYkxfn4Djqbmy/Id+HTHvaR95t2V9x4CFiIhIB+xMSsfbm44jv6QC9pamWDbGH092c4GhYMBCRESkxUorVIjYcQZfHrwiy4HtW2B1WCDcWup3CuhuDFiIiIi01NWbRZgenYCTaXmy/MeBnngrtDPMTPQ/BXQ3BixERERaaPuJ65j3zUkUllagpbUZlo/1xxM+zjBUDFiIiIi0SEm5Ch9sP4WvfkuR5Z4eLbEqLBBtHaxgyBiwEBERaYlLWYWYFp2A0zfyZfn1wY9hzu86wdQAU0B3Y8BCRESkBbYmpGHBlpMoLlPB0cYcn44LwKBOrZVultZgwEJERKSg22Uq/GlbMjYcS5Xl3p6tsHJ8IJztLZVumlZhwEJERKSQC5kFmPZVAs5mFMDICJj5hDdmDvGGibGR0k3TOgxYiIiIFLAp7hoWbU3C7XIVWttZYOW4APT1clK6WVqLAQsREVEzKiqtwKJvk7A5Pk2W+3s54bNxATJooftjwEJERNRMzqTnY9pX8biYVQSR9RErgF4b7MUUUB0wYCEiImpiGo0GG46mInxbMkor1HC2t8Cq8YHo5emodNN0RoMWdkdFRcHDwwOWlpbo1asXjhw5ct+6ycnJGD16tKxvZGSEFStWPPC9lyxZIuvNnj27IU0jIiLSKmKn2lkxiZi3+aQMVsRS5R0zBzBYaeqAZcOGDZgzZw7Cw8MRHx8Pf39/hIaGIjMzs9b6xcXF8PT0lIGIi8uD7yp59OhR/PWvf0X37t3r2ywiIiKtk3w9D8+u3o9tx6/LtM87T/ngi5d6wtGW81WaPGD59NNP8fLLL2PKlCno2rUr1q5dC2tra/zjH/+otX7Pnj2xdOlSjB8/HhYW9z9BhYWFmDhxIj7//HO0bNmyvs0iIiLSqhTQvw9fxfN/OYjL2UVo52CJr//YG68NfgzGnK/S9AFLWVkZ4uLiMHTo0P+9gbGxLB86dAiPYtq0aRg+fHiN936Q0tJS5Ofn13gQEREpLb+kXN5hWSxZLqtQY2iXNvh+5gD06NBK6aYZzqTb7OxsqFQqODvXvFukKJ85c6bBjYiJiZHpJZESqquIiAi89957Df6ZREREje3EtVwZrKTkFMPU2AjznvbB1P4d5dxMejSK300pNTUVs2bNwldffSUn8dbV/PnzkZeXV/UQ70NERKRUCuiLA5cxes1BGay4tbTCptf64v8GeDJYUWKExcnJCSYmJsjIyKhxXJQfNqH2fkSKSUzYDQoKqjomRnF+/fVXREZGytSP+Jl3E/NhHjQnhoiIqDnkFZdj7qbj+OnUnWtjaDdnfPKCPxyszJRumuEGLObm5ujRowdiY2MxcuRIeUytVsvy9OnTG9SAIUOG4OTJkzWOiQm9Pj4+eOedd2oNVoiIiLRBQsotmQJKy70NcxNjvDu8Cyb16cBRFW3YOE4saZ48eTKCg4MREhIi91UpKiqSQYYwadIkuLq6yjkmlRN1T506VfX3tLQ0JCYmwtbWFl5eXrCzs4Ovr2+Nn2FjYwNHR8d7jhMREWkDtVqDv++/jI93nkGFWoMOjtaIDAuCn5uD0k3TW/UOWMaNG4esrCwsXrwY6enpCAgIwM6dO6sm4qakpMiVQ5WuX7+OwMDAqvKyZcvkY9CgQdi7d29j9YOIiKhZ3Coqw5sbj2P3mTv7jw3v3hYRo/xgb8kUUFMy0oiZQnpALGt2cHCQE3Dt7e2Vbg4REemhY1dyMGN9Am7klcDc1BiLn+mKib3aMwXUDNdv3kuIiIioDimgtb9exPKfzkGl1sDTyQaRE4LQtR1/QW4uDFiIiIgeILuwFHO+Po5fz2XJ8siAdvjweT/YWvAS2pz4f5uIiOg+Dl+6iZnrE5BZUApLM2O891w3jA12ZwpIAQxYiIiI7iLSPlF7LmDFz+eg1gBebWwRNSEInV3slG6awWLAQkREVE1mQQne2JCIAxduyvILPdzw/ohusDbnJVNJ/L9PRET0XwcuZGNWTKKct2JlZoIPR/pidA83pZtFDFiIiIiACpUaq2LPY/WeCxCbfXR2tkPUxCCZCiLtwICFiIgMWkZ+idxb5cjlHFkOC3FH+LPdYGnGW8NoEwYsRERksPaezZRLlnOKymBjboKPRvlhRICr0s2iWjBgISIig0wBLd91Dmv2XpTlrm3tETkhEJ6tmQLSVgxYiIjIoFzPvS33Vjl29ZYsv9i7g7zLMlNA2o0BCxERGYzY0xnyxoW5xeWwszDFktHd5c0LSfsxYCEiIr1XVqHG0h/P4PN9l2XZz9VBpoA6ONoo3TSqIwYsRESk11JziuUqoMTUXFme0s8D8572gYUpU0C6hAELERHprR+T0zF343Hkl1TA3tIUS8f4I7Sbi9LNogZgwEJERHqntEKFiB1n8OXBK7Ic4N5CpoDcWlor3TRqIAYsRESkV67eLML06AScTMuT5VcGemJuaGeYmRgr3TR6BAxYiIhIb3x/4gbmfXMCBaUVaGFthk/H+uMJH2elm0WNgAELERHpvJJyFT78/hT+czhFloM7tMSqsEC0a2GldNOokTBgISIinXYpqxDTohNw+ka+LL8++DHM+V0nmDIFpFcYsBARkc76NjENCzafRFGZCo425vh0XAAGdWqtdLOoCTBgISIinXO7TIX3vktGzNFUWe7VsZVMATnbWyrdNGoiDFiIiEinXMgswLSvEnA2owBGRsCMJ7wx8wkvpoD0HAMWIiLSGZvirmHR1iTcLlfBydYCK8cHoJ+Xk9LNombAgIWIiLRecVkFFm1Nxjfx12S5n5cjPhsXgDZ2TAEZCgYsRESk1c6mF2BadDwuZBbC2Ah4Y2gnvP64F0xEgQwGAxYiItJKGo0GG46mInxbMkor1HC2FymgQPT2dFS6aaQABixERKR1Cksr8O6Wk/g28bosi6XKYtdaR1sLpZtGCmHAQkREWiX5eh5mRCfgUnaRTPu89WRn/HGgJ4yZAjJoDFiIiEhrUkD/+S0FH2w/hbIKNdo6WGJ1WCCCPVop3TTSAgxYiIhIcfkl5Zi/+aS8eaEwxKcNlo3xR0sbc6WbRlqiQbvsREVFwcPDA5aWlujVqxeOHDly37rJyckYPXq0rG9kZIQVK1bcUyciIgI9e/aEnZ0d2rRpg5EjR+Ls2bMNaRoREemYk9fy8Myq/TJYMTU2wsLhXfC3ycEMVujRApYNGzZgzpw5CA8PR3x8PPz9/REaGorMzMxa6xcXF8PT0xNLliyBi4tLrXV++eUXTJs2DYcPH8auXbtQXl6OJ598EkVFRfVtHhER6VAK6MsDlzF6zUGk5BTDtYUVNr7aB/83wFP+gktUnZFGfGLqQYyoiNGQyMhIWVar1XB3d8eMGTMwb968B75WjLLMnj1bPh4kKytLjrSIQGbgwIF1ald+fj4cHByQl5cHe3v7evSIiIiaW15xOd7+5jh+TM6Q5Se7OmPpC/5wsDZTumnUzOp6/a7XHJaysjLExcVh/vz5VceMjY0xdOhQHDp0CI1FNFpo1er+E61KS0vlo3qHiYhI+yWk3MKM9Qm4dus2zE2MsWCYDyb3vTNtgKhRUkLZ2dlQqVRwdnaucVyU09PT0RjEiI0YgenXrx98fX3vW0/MexERWeVDjPIQEZH2EgP6f9t3CWPWHpLBSvtW1vjmtb54qV9HBiuke6uExFyWpKQk7N+//4H1xCiPmEtTfYSFQQsRkXa6VVSGtzYeR+yZO/Mdh/u1RcRoP9hbMgVETRCwODk5wcTEBBkZd3KOlUT5fhNq62P69OnYvn07fv31V7i5uT2wroWFhXwQEZF2O3YlBzPXJ+B6XgnMTY2x+JmumNirPUdVqOlSQubm5ujRowdiY2NrpHBEuU+fPniUYUIRrGzZsgW7d+9Gx44dG/xeRESkHdRqDf6y9wLGrTssg5WOTjbY8npf/L53BwYr1PQpIZGGmTx5MoKDgxESEiL3VRHLj6dMmSKfnzRpElxdXeUck8qJuqdOnar6e1paGhITE2FrawsvL6+qNFB0dDS+/fZbuRdL5XwYMTfFysqq/r0iIiJF3SwsxZyvj+OXc1myPCKgHf78vB9sLbRuJgLp67JmQSxpXrp0qQwsAgICsGrVKrncWRg8eLBcvvzll1/K8pUrV2odMRk0aBD27t17pxH3ibS/+OILvPTSS3VqE5c1ExFph98u3cTMmARk5JfCwtQY74/ohrHB7hxVoUe6fjcoYNFGDFiIiJSlEimgPRfw2c/noNYAj7W2wV8m9kBnFzulm0aGtg8LERFRbbIKSjF7QwIOXLgpy6OD3PDByG6wNudlhhoHP0lERPRIDlzIxqyYRGQXlsLKzAQfjPTFCz0evNKTqL4YsBARUYNTQCtjz2P17vMQkws6O9shamIgvNowBUSNjwELERHVW0Z+CWbFJODwpRxZHt/THeHPdoOVuYnSTSM9xYCFiIjqRSxVnrMhETeLymBjboKPRvlhRICr0s0iPceAhYiI6qRCpcbyXeewZu9FWe7S1h5REwLh2dpW6aaRAWDAQkRED3U997bcXv/Y1Vuy/Pve7bFweFdYmjEFRM2DAQsRET3Q7jMZctfa3OJy2FmYypsWPtO9ndLNIgPDgIWIiGpVrlJj6Y9nse7XS7Ls5+qAyAmB6OBoo3TTyAAxYCEiontcu1WM6dEJSEzNleWX+npg/jAfWJgyBUTKYMBCREQ1/JicjrkbjyO/pAL2lqZYOsYfod1clG4WGTgGLEREJJVVqBHxw2l8ceCKLAe4t8DqsEC4t7JWumlEDFiIiAhIuVmM6evjceJaniy/PKAj5ob6wNzUWOmmEUkMWIiIDNyOkzfwzqYTKCitQAtrMywf448hXZyVbhZRDQxYiIgMVEm5Cn/+/jT+ffiqLAd3aIlVYYFo18JK6aYR3YMBCxGRAbqcXYRpX8Xj1I18WX5t8GOY87tOMDNhCoi0EwMWIiID821iGhZsPomiMhVa2Zjj07H+GNy5jdLNInogBixERAaUAnrvu2SsP5IqyyEdW2HV+EC4OFgq3TSih2LAQkRkAC5kFsoU0NmMAhgZATMe98LMId4wZQqIdAQDFiIiPfdN3DUs3JqE2+UqONlaYMW4APT3dlK6WUT1woCFiEhPFZdVYPG3ydgUd02W+3k54rNxAWhjxxQQ6R4GLEREeuhcRoFMAZ3PLISxETB7aCdMe9wLJqJApIMYsBAR6RGNRoOvj6UifFsySsrVaGNnIfdW6e3pqHTTiB4JAxYiIj1RWFqBhVtOYmvidVke2Km1XLIs5q0Q6ToGLEREeuDU9XxMj47HpewimfZ588lOeHXgYzBmCoj0BAMWIiIdTwF99VsK3t9+St5tua2DpUwB9fRopXTTiBoVAxYiIh1VUFKOeZtP4vsTN2T5CZ828saFLW3MlW4aUaNjwEJEpINOXsvD9PXxuHqzGKbGRnjnKR9M7d+RKSDSWwxYiIh0LAX0z4NX8NGOMyhTqeHawgqrJwQiqH1LpZtG1KQYsBAR6Yi82+V4Z9MJ7ExOl+Unuzpj6Qv+cLA2U7ppRE2OAQsRkQ5ITM2Vq4Cu3boNMxMjLBjWBS/19YCRuDEQkQFgwEJEpOUpoL/vv4wlP5xBhVqD9q2sETkhEN3dWijdNKJm1aDbdEZFRcHDwwOWlpbo1asXjhw5ct+6ycnJGD16tKwvfhNYsWLFI78nEZEhyC0uw8v/OoYPvz8tg5Vhfi7YPrM/gxUySPUOWDZs2IA5c+YgPDwc8fHx8Pf3R2hoKDIzM2utX1xcDE9PTyxZsgQuLi6N8p5ERPou7moOhq3ch59PZ8Lc1BgfjPRF1IQg2FtyvgoZJiONGG+sBzH60bNnT0RGRsqyWq2Gu7s7ZsyYgXnz5j3wtWIEZfbs2fLRWO9ZKT8/Hw4ODsjLy4O9vX19ukREpDXUag3W7buEpT+ehUqtQUcnG5kC6tbOQemmETWJul6/6zXCUlZWhri4OAwdOvR/b2BsLMuHDh1qUEMb+p6lpaWyk9UfRES67GZhKf7wz6NyvooIVp7zb4fvZvRnsEJU34AlOzsbKpUKzs7ONY6Lcnr6nWV29dXQ94yIiJARWeVDjMgQEemq3y7dxLBV+7D3bBYsTI2xZJQfVo4PgK0F10YQNXjSrTaYP3++HD6qfKSmpirdJCKiehMjKatjzyPs88PIyC/FY61t8O30fhgf0p5LlomqqVfo7uTkBBMTE2RkZNQ4Lsr3m1DbVO9pYWEhH0REuiqroBRvbEjE/gvZsjwqyBUfjPCFDUdViB5thMXc3Bw9evRAbGxs1TExQVaU+/TpU5+3atL3JCLSdgcvZMsUkAhWrMxMsGyMPz4dG8Bgheg+6v3NEMuPJ0+ejODgYISEhMh9VYqKijBlyhT5/KRJk+Dq6irnmFROqj116lTV39PS0pCYmAhbW1t4eXnV6T2JiPQpBbQy9jxW7z4PsUazk7OtXK7s7WyndNOI9CtgGTduHLKysrB48WI5KTYgIAA7d+6smjSbkpIiV/lUun79OgIDA6vKy5Ytk49BgwZh7969dXpPIiJ9kJFfglkxCTh8KUeWx/d0R/iz3WBlbqJ004j0bx8WbcV9WIhIm/16LkvOV7lZVAYbcxN8NMoPIwJclW4Wkc5cv5ksJSJqQhUqNT77+Rz+sveiTAF1aWuPqAmB8Gxtq3TTiHQKAxYioiZyI+82Zq5PwNErt2R5Yq/2WPRMV1iaMQVEVF8MWIiImsCeM5mY83UibhWXy83floz2wzPd2yndLCKdxYCFiKgRlavUWPbjWfz110uy7OsqUkBB6OBoo3TTiHQaAxYiokZy7VYxZqxPQEJKriy/1NcD84f5wMKUKSCiR8WAhYioEfyUnI65m04g73Y57CxNsfSF7njKt63SzSLSGwxYiIgeQVmFGhE/nMYXB67Isr97C0SGBcK9lbXSTSPSKwxYiIgaKOVmMaavj8eJa3my/PKAjpgb6gNzU529ryyR1mLAQkTUAD+cvIG3N51AQWkFWlibYdkL/hjalbtzEzUVBixERPVQUq7CRztO41+Hrspyjw4tsSosEK4trJRuGpFeY8BCRFRHl7OLMD06HsnX82X51UGP4c0nO8HMhCkgoqbGgIWIqA62Hb+OBZtPorC0Aq1szPHpWH8M7txG6WYRGQwGLERED0kBvffdKaw/kiLLIR1bYdX4QLg4WCrdNCKDwoCFiOg+LmQWyhTQmfQCGBkB0x/3wqwh3jBlCoio2TFgISKqxeb4a1i4NQnFZSo42ZpjxbhA9Pd2UrpZRAaLAQsRUTXFZRUI/zYZG+OuyXLfxxyxYlwA2tgzBUSkJAYsRET/dS6jANO+isf5zEIYGwGzhnTC9Ce8YCIKRKQoBixEZPA0Gg02HruGxduSUFKuRhs7C6wcH4g+jzkq3TQi+i8GLERk0IpKK+RclS0JabI8wNsJn40LgJOthdJNI6JqGLAQkcE6fSNfpoAuZRfJtM+c33XCa4MegzFTQERahwELERlkCij6SIrcX0XcbdnF3hKrJwSip0crpZtGRPfBgIWIDEpBSTnmbz6J7SduyPITPm2wbIy/3L2WiLQXAxYiMhhJaXmYFh2PqzeLYWpshLef6oz/6+/JFBCRDmDAQkQGkQISd1f+8/enUaZSyzsrixRQUPuWSjeNiOqIAQsR6bW82+V4Z9MJ7ExOl+XfdXXG0he6o4U1U0BEuoQBCxHprcTUXHkvoGu3bsPMxAjzn+6CKf08YCRuDEREOoUBCxHpZQro7/sv4+OdZ1Cu0sC9lRUiw4Lg795C6aYRUQMxYCEivZJbXIa3Np7Az6czZHmYnwuWjO4Oe0szpZtGRI+AAQsR6Y24q7cwIzoe1/NKYG5ijEXPdMHve3dgCohIDzBgISKdp1ZrsG7fJSz98SxUag08HK0ROSEIvq4OSjeNiBoJAxYi0mk5RWWY83Ui9p7NkuXn/Nvho1F+sLXgP29E+sS4IS+KioqCh4cHLC0t0atXLxw5cuSB9Tdu3AgfHx9Z38/PDzt27KjxfGFhIaZPnw43NzdYWVmha9euWLt2bUOaRkQG5MjlHAxbuU8GKxamxogY5YeV4wMYrBDpoXoHLBs2bMCcOXMQHh6O+Ph4+Pv7IzQ0FJmZmbXWP3jwIMLCwjB16lQkJCRg5MiR8pGUlFRVR7zfzp078Z///AenT5/G7NmzZQCzbdu2R+sdEeltCihy93mMX3cI6fkl8Gxtg63T+iEspD3nqxDpKSONWP9XD2JEpWfPnoiMjJRltVoNd3d3zJgxA/Pmzbun/rhx41BUVITt27dXHevduzcCAgKqRlF8fX1lvUWLFlXV6dGjB55++ml8+OGHdWpXfn4+HBwckJeXB3t7+/p0iYh0SFZBqUwB7TufLcujAl3xwUhf2HBUhUgn1fX6Xa8RlrKyMsTFxWHo0KH/ewNjY1k+dOhQra8Rx6vXF8SITPX6ffv2laMpaWlpcv+EPXv24Ny5c3jyySfv25bS0lLZyeoPItJvBy9kY9iqfTJYsTQzljvWfjougMEKkQGo17c8OzsbKpUKzs7ONY6L8pkzZ2p9TXp6eq31xfFKq1evxiuvvCLnsJiamsog6PPPP8fAgQPv25aIiAi899579Wk+EekosfJnVex5rNp9HmJMuJOzLaImBMHb2U7pphFRM9GKX0tEwHL48GE5ytKhQwf8+uuvmDZtGtq1a3fP6Eyl+fPny7kvlcQIi0hNEZF+ycwvwayYRBy6dFOWxwW740/PdYOVuYnSTSMibQ1YnJycYGJigoyMOztIVhJlFxeXWl8jjj+o/u3bt7FgwQJs2bIFw4cPl8e6d++OxMRELFu27L4Bi4WFhXwQkf7adz4Lb2xIRHZhGazNTfDR834YGeiqdLOISAH1msNibm4uJ8PGxsZWHROTbkW5T58+tb5GHK9eX9i1a1dV/fLycvkQaaDqRGAk3puIDE+FSo1lP57FpH8ckcGKj4sdvpvRn8EKkQGrd0pIpGEmT56M4OBghISEYMWKFXIV0JQpU+TzkyZNgqurq5xjIsyaNQuDBg3C8uXL5QhKTEwMjh07hnXr1snnxYxg8fzcuXPlHiwiJfTLL7/gX//6Fz799NPG7i8Rabkbebcxa30ijlzJkeWJvdpj0TNdYWnGFBCRIat3wCKWH2dlZWHx4sVy4qxYniz2UKmcWJuSklJjtESsAIqOjsbChQtl6sfb2xtbt26VS5kriSBGzEmZOHEicnJyZNDy5z//Ga+++mpj9ZOIdMCeM5lyyfKt4nK5+ZvYCO5Z/3ZKN4uIdHEfFm3FfViIdFf5f1NAf/31kiz7utojMiwIHk42SjeNiLTk+q0Vq4SIyHCl5d6Wd1iOT8mV5Zf6emD+MB9YmDIFRET/w4CFiBSz61QG3tp4HHm3y2FnaSo3gnvKt63SzSIiLcSAhYiaXVmFGkt+OIN/HLgsy/5uDoicEAT3VtZKN42ItBQDFiJqVqk5xZgeHY/j1/Jk+f/6d8TbT/nA3LRBN48nIgPBgIWIms3OpBuYu+kECkoq4GBlhuVj/DG0a81bdxAR1YYBCxE1uZJyFSJ2nMY/D12V5aD2LbB6QhBcW1gp3TQi0hEMWIioSV3JLsK06HgkX79zR/U/DvLEW092hpkJU0BEVHcMWIioyXx3/Drmbz6JwtIKtLIxx/Kx/ni8cxulm0VEOogBCxE1SQro/e2nEP1biiyHeLTCqrBAuDhYKt00ItJRDFiIqFFdzCrEtK/icSa9AEZGwPTHvTBriDdMmQIiokfAgIWIGs2WhGt4d0sSistUcLI1x2fjAjDAu7XSzSIiPcCAhYge2e0yFRZ/m4SNcddkuY+nI1aOD0Abe6aAiKhxMGAhokdyLqNApoDOZxbC2AiYNaQTpj/hBRNRICJqJAxYiKhBxI3exYiKGFkpKVejtZ0FVo0PRJ/HHJVuGhHpIQYsRFRvRaUVWLQ1CZsT0mR5gLeTnK/iZGuhdNOISE8xYCGiejl9I19uBHcpq0imgN58sjNeG/QYjJkCIqImxICFiOqcAlp/JBXvfZeM0go1XOwt5d4qIR1bKd00IjIADFiI6KEKSsqxYEuS3LlWeLxzaywfGyB3ryUiag4MWIjogZLS8jA9Oh5XbhbD1NgIc0M74+UBnkwBEVGzYsBCRPdNAf378FV8uP00ylRqeWdlkQLq0aGl0k0jIgPEgIWI7pF3uxzzvjmBH5LSZXloF2csG9MdLayZAiIiZTBgIaIajqfmYvr6eKTm3IaZiRHmPd0Ff+jnASNxYyAiIoUwYCGiqhTQPw5cwZIfTqNcpYF7KytEhgXB372F0k0jImLAQkRAbnEZ3tp4Aj+fzpDlp31dsGR0dzhYmSndNCIiiQELkYGLu3oLM9cnIC33NsxNjLHwmS54sXcHpoCISKswYCEyUGq1Bp/vu4SlP55FhVoDD0drRE4Igq+rg9JNIyK6BwMWIgOUU1SGN79OxJ6zWbL8rH87fPS8L+wsmQIiIu3EgIXIwBy5nCNTQOn5JbAwNUb4s90QFuLOFBARaTUGLEQGlAJa88tFfLrrHFRqDTxb2yBqQhC6tLVXumlERA/FgIXIAGQXluKNDYnYdz5blkcFuuKDkb6wseA/AUSkG/ivFZGeO3gxG7NiEpFVUApLM2O8P8IXY3q4MQVERDqFAQuRnhJpn9W7z2NV7HmoNYB3G1tETQxCJ2c7pZtGRFRvxvV/CRAVFQUPDw9YWlqiV69eOHLkyAPrb9y4ET4+PrK+n58fduzYcU+d06dP47nnnoODgwNsbGzQs2dPpKSkNKR5RAYvM78EL/79N6z4+U6wMjbYDdum92ewQkSGE7Bs2LABc+bMQXh4OOLj4+Hv74/Q0FBkZmbWWv/gwYMICwvD1KlTkZCQgJEjR8pHUlJSVZ2LFy+if//+MqjZu3cvTpw4gUWLFskAh4jqZ9/5LAxbtQ8HL96EtbkJPhvnj09e8IeVuYnSTSMiajAjjbiBSD2IERUx+hEZGSnLarUa7u7umDFjBubNm3dP/XHjxqGoqAjbt2+vOta7d28EBARg7dq1sjx+/HiYmZnh3//+d4M7kp+fL0dn8vLyYG/PVQ9keCpUajmiErX3AsS32sfFTm4E59XGVummERE98vW7XiMsZWVliIuLw9ChQ//3BsbGsnzo0KFaXyOOV68viBGZyvoi4Pn+++/RqVMnebxNmzYyKNq6desD21JaWio7Wf1BZKjS80ow4fPfELnnTrAyoVd7bJ3Wj8EKEemNegUs2dnZUKlUcHZ2rnFclNPT02t9jTj+oPoilVRYWIglS5bgqaeewk8//YTnn38eo0aNwi+//HLftkRERMiIrPIhRnmIDNGes5kyBXTkSg5sLUyxKiwQHz3vB0szpoCISH8ovkpIjLAII0aMwBtvvCH/LtJFYu6LSBkNGjSo1tfNnz9fzqWpJEZYGLSQISlXqbHsp7P46y+XZLlbO3u5EZyHk43STSMiUjZgcXJygomJCTIy7tyCvpIou7i41PoacfxB9cV7mpqaomvXrjXqdOnSBfv3779vWywsLOSDyBCJOyuL7fXFnZaFyX06YP6wLhxVISK9Va+UkLm5OXr06IHY2NgaIySi3KdPn1pfI45Xry/s2rWrqr54TzGJ9+zZszXqnDt3Dh06dKhP84gMwq5TGRi2cp8MVuwsTbFmYhDeG+HLYIWI9Fq9U0IiDTN58mQEBwcjJCQEK1askKuApkyZIp+fNGkSXF1d5RwTYdasWTKts3z5cgwfPhwxMTE4duwY1q1bV/Wec+fOlauJBg4ciMcffxw7d+7Ed999J5c4E9EdZRVqfLzzDP6+/7Is+7s5YHVYENo7WivdNCIi7QtYRGCRlZWFxYsXy4mzYr6JCDAqJ9aKzd7EyqFKffv2RXR0NBYuXIgFCxbA29tbrgDy9fWtqiMm2Yr5KiLImTlzJjp37oxvvvlG7s1CREBqTjGmr0/A8dRcWZ7avyPeecoH5qYN2vuRiEj/92HRVtyHhfTVzqQbmLvpBApKKuBgZYZlY/zxu641V94REen79VvxVUJEVLvSChU++v40/nnoqiwHtW8hlyy7tWQKiIgMDwMWIi10JbsI09fHIyntzoaIfxzkibee7AwzE6aAiMgwMWAh0jLbT1zHvG9OorC0Ai2tzfDp2AA87tNG6WYRESmKAQuRligpV+H97acQ/dudu5T39GgpU0BtHayUbhoRkeIYsBBpgYtZhZj2VTzOpBfAyAiYNtgLs4d6w5QpICIiiQELkcK2JFzDu1uSUFymgqONOVaMD8AA79ZKN4uISKswYCFSyO0yFcK3JeHrY9dkuY+nI1aOD0Abe0ulm0ZEpHUYsBAp4HxGAaZFx+NcRqFMAc18whszh3jDxNhI6aYREWklBixEzWzjsVQs+jYJJeVqtLazwMpxAejr5aR0s4iItBoDFqJmUlRaIQOVzfFpsjzA20kuWRZBCxERPRgDFqJmcCY9X64CuphVBJH1efPJznht0GMwZgqIiKhOGLAQNSFxq66Yo6n407ZklFao4WJvKfdWCenYSummERHpFAYsRE2koKQcC7Yk4bvj12V5cOfWMgXUysZc6aYREekcBixETSApLQ/To+Nx5WaxXPnzdmhnvDzAkykgIqIGYsBC1MgpoP8cvooPtp9GmUqNdg6WWD0hCD06tFS6aUREOo0BC1EjyS8px7xvTmDHyXRZHtrFGcvGdEcLa6aAiIgeFQMWokZwPDUX09fHIzXnNsxMjPDOUz6Y2r8jjMSucERE9MgYsBA9YgroiwNXEPHDaZSrNHBraYXICUEIcG+hdNOIiPQKAxaiBsotLsPcTSew61SGLD/VzQUfv9AdDlZmSjeNiEjvMGAhaoD4lFuYEZ2AtNzbMDcxxsJnuuDF3h2YAiIiaiIMWIjqQa3W4G/7L+GTnWdRodagg6M1oiYEwdfVQemmERHpNQYsRHWUU1SGtzYex+4zmbL8TPe2iBjlBztLpoCIiJoaAxaiOjh6JQcz1yfgRl4JzE2N8adnuyEsxJ0pICKiZsKAheghKaA1v1zEp7vOQaXWwNPJBlETg9Clrb3STSMiMigMWIjuI7uwFG9sSMS+89my/HygKz4c6QsbC35tiIiaG//lJarFoYs3MSsmAZkFpbA0M8b7z/liTLAbU0BERAphwEJUjUj7RO6+gJWx56DWAN5tbGUKqJOzndJNIyIyaAxYiP4rs6AEs2MScfDiTVke08MN743oBmtzfk2IiJTGf4mJAOw/n43ZGxKQXVgGa3MTOVdlVJCb0s0iIqL/YsBCBq1CpcbK2POI3HMBGg3g42In7wXk1cZW6aYREVE1DFjIYKXnlWBmTAKOXM6R5bCQ9gh/tisszUyUbhoREd3FGA0QFRUFDw8PWFpaolevXjhy5MgD62/cuBE+Pj6yvp+fH3bs2HHfuq+++qpcibFixYqGNI2oTvaezcSwVftksGJjboJVYYFy11oGK0REehKwbNiwAXPmzEF4eDji4+Ph7++P0NBQZGbe2a78bgcPHkRYWBimTp2KhIQEjBw5Uj6SkpLuqbtlyxYcPnwY7dq1a1hviB6iXKXGkh/O4KUvjsqt9ru1s8f2mQPwnD8/c0RE2sxIoxGZ+7oTIyo9e/ZEZGSkLKvVari7u2PGjBmYN2/ePfXHjRuHoqIibN++vepY7969ERAQgLVr11YdS0tLk+/9448/Yvjw4Zg9e7Z81FV+fj4cHByQl5cHe3vuQkr3up57GzPWJyDu6i1ZntSnAxYM68JRFSIiBdX1+l2vEZaysjLExcVh6NCh/3sDY2NZPnToUK2vEcer1xfEiEz1+iLoefHFFzF37lx069atTm0pLS2Vnaz+ILqfn09lyBSQCFbsLEzxl4lBeH+EL4MVIiIdUa+AJTs7GyqVCs7OzjWOi3J6enqtrxHHH1b/448/hqmpKWbOnFnntkRERMiIrPIhRnmI7lZWocaH20/h//51DLnF5eju5oDvZw7AML+2SjeNiIh0aZWQGLFZuXKlnA9Tn23P58+fL+fSVBIjLAxaqLrUnGJMX5+A46m5svyHfh0x72kfebdlIiLS44DFyckJJiYmyMjIqHFclF1cXGp9jTj+oPr79u2TE3bbt29f9bwYxXnzzTflSqErV67U+r4WFhbyQVSbnUnpmLvpOApKKmBvaYplY/zxZLfaP6NERKT96vWrprm5OXr06IHY2Nga809EuU+fPrW+RhyvXl/YtWtXVX0xd+XEiRNITEyseohVQmI+i5iAS1QfpRUq/GlbMl79T5wMVgLbt8COWQMYrBARGVpKSKRhJk+ejODgYISEhMhRELEKaMqUKfL5SZMmwdXVVc4xEWbNmoVBgwZh+fLlcvVPTEwMjh07hnXr1snnHR0d5aM6MzMzOQLTuXPnxuklGYSrN4swPToBJ9PyZPmPAz3xVmhnmJkwBUREZHABi1imnJWVhcWLF8uJs2J58s6dO6sm1qakpMiVQ5X69u2L6OhoLFy4EAsWLIC3tze2bt0KX1/fxu0JGbTtJ65j3jcnUVhagZbWZlg+1h9P+NSc7E1ERAa0D4u24j4shqmkXIUPtp/CV7+lyHJPj5Zy19q2DlZKN42IiBrx+q34KiGihrqUVYhp0Qk4fSMfYoHZ64MfwxtDO8GUKSAiIr3DgIV00taENCzYchLFZSo42pjjs3EBGNiptdLNIiKiJsKAhXTK7bI7q4A2HEuV5d6erbByfCCc7S2VbhoRETUhBiykM85nFGBadDzOZRTKFNDMJ7wxc4g3TIzrvuEgERHpJgYspBM2HkvF4m+TcbtchdZ2Flg5LgB9vZyUbhYRETUTBiyk1YpKK7Do2yRsjk+T5f5eTnK+ighaiIjIcDBgIa11Jj0f076Kx8WsIoisz5zfdcLrg71gzBQQEZHBYcBCWkdsDbThaCrCtyWjtEINZ3sLrBofiF6eNXdEJiIiw8GAhbSK2Kl2weaT2Hb8uiwP6tQan471h6MtU0BERIaMAQtpjeTrefJeQJezi+TKn7mhnfHKAE+mgIiIiAELaUcK6D+/pcgt9ssq1GjnYInVEwLRo0MrpZtGRERaggELKSq/pBzzvzmJ70/ekOWhXdpg6Qv+aGljrnTTiIhIizBgIcWcuJYrU0ApOcUwNTbCvKd9MLV/RxiJXeGIiIiqYcBCiqSAvjx4BR/tOI1ylQZuLa0QOSEIAe4tlG4aERFpKQYs1Kzyissxd9Nx/HQqQ5ZDuznjkxf84WBlpnTTiIhIizFgoWaTkHJLpoDScm/D3MQY7w7vgkl9OjAFRERED8WAhZqcWq3B3/dfxsc7z6BCrUEHR2tEhgXBz81B6aYREZGOYMBCTepWURne3Hgcu89kyvLw7m2xZJQf7CyZAiIiorpjwEJN5tiVHMxYn4AbeSUwNzVG+LNdMSGkPVNARERUbwxYqElSQGt/vYjlP52DSq2Bp5ONXAXUtZ290k0jIiIdxYCFGlV2YSnmfH0cv57LkuWRAe3w4fN+sLXgR42IiBqOVxFqNIcv3cTM9QnILCiFpZkx3n/OF2OC3ZgCIiKiR8aAhR6ZSPtE7bmAFT+fg1oDeLWxRdSEIHR2sVO6aUREpCcYsNAjySwowRsbEnHgwk1ZfqGHG94f0Q3W5vxoERFR4+FVhRrswIVszIpJlPNWrMxM8OFIX4zu4aZ0s4iISA8xYKF6q1CpsSr2PFbvuQCNBvBxsZOrgEQqiIiIqCkwYKF6ycgvkXurHLmcI8thIe4If7YbLM1MlG4aERHpMQYsVGd7z2bKJcs5RWWwMTfBR6P8MCLAVelmERGRAWDAQnVKAS3fdQ5r9l6U5a5t7RE1MQgdnWyUbhoRERkIBiz0QNdzb8u9VY5dvSXLL/buIO+yzBQQERE1JwYsdF+xpzPkjQtzi8thZ2GKj1/ojmF+bZVuFhERGSAGLHSPsgo1lv54Bp/vuyzL3d0cEBkWhPaO1ko3jYiIDJRxQ14UFRUFDw8PWFpaolevXjhy5MgD62/cuBE+Pj6yvp+fH3bs2FH1XHl5Od555x153MbGBu3atcOkSZNw/fr1hjSNHlFqTjHG/vVQVbAypZ8HNr7ah8EKERHpVsCyYcMGzJkzB+Hh4YiPj4e/vz9CQ0ORmZlZa/2DBw8iLCwMU6dORUJCAkaOHCkfSUlJ8vni4mL5PosWLZJ/bt68GWfPnsVzzz336L2jevkxOR3DV+1DYmou7C1N8dcXe8glyxamnK9CRETKMtJoxNZfdSdGVHr27InIyEhZVqvVcHd3x4wZMzBv3rx76o8bNw5FRUXYvn171bHevXsjICAAa9eurfVnHD16FCEhIbh69Srat29fp3bl5+fDwcEBeXl5sLe3r0+XDF5phQoRO87gy4NXZDmwfQusDguEW0uOqhARUdOq6/W7XiMsZWVliIuLw9ChQ//3BsbGsnzo0KFaXyOOV68viBGZ+9UXRKPFHX5btGhx3zqlpaWyk9UfVH9XbxbhhTWHqoKVVwZ64us/9mGwQkREWqVeAUt2djZUKhWcnZ1rHBfl9PT0Wl8jjtenfklJiZzTItJID4q0IiIiZERW+RCjPFQ/35+4gWdW7cfJtDy0tDbDP14KxoJhXWBm0qCpTURERE1Gq65MYgLu2LFjIbJUa9aseWDd+fPny5GYykdqamqztVPXlZSrsHDrSUyLjkdBaQWCO7TEjlkD8IRPzcCSiIhIJ5c1Ozk5wcTEBBkZGTWOi7KLi0utrxHH61K/MlgR81Z279790HkoFhYW8kH1cymrENOiE3D6xp0U2uuDH8Oc33WCKUdViIhIi9XrKmVubo4ePXogNja26piYdCvKffr0qfU14nj1+sKuXbtq1K8MVs6fP4+ff/4Zjo6O9e8JPdS3iWl4dvV+Gaw42pjjn38IwdtP+TBYISIi/ds4Tixpnjx5MoKDg+VKnhUrVshVQFOmTJHPiz1UXF1d5RwTYdasWRg0aBCWL1+O4cOHIyYmBseOHcO6deuqgpUXXnhBLmkWK4nEHJnK+S2tWrWSQRI9mttlKrz3XTJijt5Jm/X2bIWV4wPhbG+pdNOIiIiaJmARy5SzsrKwePFiGViI5ck7d+6smlibkpIiVw5V6tu3L6Kjo7Fw4UIsWLAA3t7e2Lp1K3x9feXzaWlp2LZtm/y7eK/q9uzZg8GDB9e3iVTNhcwCTPsqAWczCmBkBMx4whuzhnjDxNhI6aYRERE13T4s2or7sNxrU9w1LNqahNvlKjjZWmDl+AD083JSullERET1vn7zXkJ6qLisAou2JuOb+Guy3M/LEZ+NC0AbO6aAiIhINzFg0TNn0wvw+ldxuJhVBJH1eWNoJ7z+uBdTQEREpNMYsOgJkdnbcDQV4duSUVqhhrO9SAEForcnV1wREZHuY8CiBwpLK/DulpP4NvHOHa4HdWqNT8f6w9GW+9QQEZF+YMCi45Kv52FGdAIuZRfJtM9bT3bGHwd6wpgpICIi0iMMWHQ4BfSf31LwwfZTKKtQo62DpbzDcrBHK6WbRkRE1OgYsOig/JJyzN98Ut68UBji0wbLxvijpQ032SMiIv3EgEXHnLyWJ29amJJTDFNjI8x72gdT+3eEkdgVjoiISE8xYNGhFNA/D17BRzvOoEylhmsLK0ROCERg+5ZKN42IiKjJMWDRAXnF5Xj7m+P4MfnOXa+f7OqMpS/4w8HaTOmmERERNQsGLFouIeUWZqxPwLVbt2FuYowFw3wwua8HU0BERGRQGLBocQrob/su4+OdZ1Ch1qB9K2tETQiCn5uD0k0jIiJqdgxYtNCtojK8tfE4Ys9kyvLw7m0RMcoP9pZMARERkWFiwKJljl3Jwcz1CbieVwJzU2MsfqYrJvZqzxQQEREZNAYsWkKt1mDtrxex/KdzUKk16OhkI1cBdWvHFBAREREDFi1ws7AUc74+jl/OZcnyiIB2+PPzfrC14OkhIiISeEVU2G+XbmJmTAIy8kthYWqM90d0w9hgd6aAiIiIqmHAohCR9vnLngv47OdzUGsArza2chVQZxc7pZtGRESkdRiwKCCroBSzNyTgwIWbsjw6yA0fjOwGa3OeDiIiotrwCtnMDlzIxqyYRGQXlsLKzAQfjPTFCz3clG4WERGRVmPA0owpoJWx57F693loNEBnZztETQyEVxumgIiIiB6GAUszyMgvkXur/HY5R5bH93RH+LPdYGVuonTTiIiIdAIDliYmlirP2ZCIm0VlsDE3wUej/DAiwFXpZhEREekUBixNpEKlxvJd57Bm70VZ7tLWHlETAuHZ2lbpphEREekcBixN4HrubZkCOnb1liy/2LsD3h3eBZZmTAERERE1BAOWRrb7TIbctTa3uBx2FqZYMrq7vHkhERERNRwDlkZSrlJj6Y9nse7XS7Ls5+og7wXUwdFG6aYRERHpPAYsjeDarWJMj05AYmquLL/U1wPzh/nAwpQpICIiosbAgOUR/ZicjrkbjyO/pAL2lqZYOsYfod1clG4WERGRXmHA0kBlFWpE/HAaXxy4IssB7i2wOiwQ7q2slW4aERGR3mHA0gApN4sxfX08TlzLk+WXB3TE3FAfmJsaK900IiIivdSgK2xUVBQ8PDxgaWmJXr164ciRIw+sv3HjRvj4+Mj6fn5+2LFjR43nNRoNFi9ejLZt28LKygpDhw7F+fPnoY12nLyB4av2yWClhbUZ/j45GO8O78pghYiIqAnV+yq7YcMGzJkzB+Hh4YiPj4e/vz9CQ0ORmZlZa/2DBw8iLCwMU6dORUJCAkaOHCkfSUlJVXU++eQTrFq1CmvXrsVvv/0GGxsb+Z4lJSXQFiXlKizamoTXv4pHQWkFgju0xI6ZAzCki7PSTSMiItJ7RhoxvFEPYkSlZ8+eiIyMlGW1Wg13d3fMmDED8+bNu6f+uHHjUFRUhO3bt1cd6927NwICAmSAIn58u3bt8Oabb+Ktt96Sz+fl5cHZ2Rlffvklxo8fX6d25efnw8HBQb7W3t4ejelydhGmfRWPUzfyZfn1wY/hjd91gpkJR1WIiIgeRV2v3/W64paVlSEuLk6mbKrewNhYlg8dOlTra8Tx6vUFMXpSWf/y5ctIT0+vUUc0XARG93tPobS0VHay+qMpfJuYhmdW7ZPBSisbc/zzDyF4+ykfBitERETNqF5X3ezsbKhUKjn6UZ0oi6CjNuL4g+pX/lmf9xQiIiJkYFP5EKM8jS09rwRvbzqBojIVenVshR9mDcCgTq0b/ecQERHRg+nsMMH8+fPl8FHlIzU1tdF/houDJd57rhtmPuGFr/6vF5ztLRv9ZxAREVEjL2t2cnKCiYkJMjIyahwXZReX2jdLE8cfVL/yT3FMrBKqXkfMc7kfCwsL+Whq40PaN/nPICIiokYcYTE3N0ePHj0QGxtbdUxMuhXlPn361Poacbx6fWHXrl1V9Tt27CiDlup1xHwUsVrofu9JREREhqXeG8eJJc2TJ09GcHAwQkJCsGLFCrkKaMqUKfL5SZMmwdXVVc4xEWbNmoVBgwZh+fLlGD58OGJiYnDs2DGsW7dOPm9kZITZs2fjww8/hLe3twxgFi1aJFcOieXPRERERPUOWMQy5aysLLnRm5gUK9I2O3furJo0m5KSIlcOVerbty+io6OxcOFCLFiwQAYlW7duha+vb1Wdt99+WwY9r7zyCnJzc9G/f3/5nmKjOSIiIqJ678OirZpyHxYiIiLSoX1YiIiIiJTAgIWIiIi0HgMWIiIi0noMWIiIiEjrMWAhIiIirceAhYiIiLQeAxYiIiLSegxYiIiISOsxYCEiIiL925pfW1Vu2Ct2zCMiIiLdUHndftjG+3oTsBQUFMg/3d3dlW4KERERNeA6Lrbo1/t7CanValy/fh12dnbyDtCNGfmJICg1NVUv71Gk7/0zhD7qe/8MoY/sn+7T9z7mN2H/RBgigpV27drVuHmy3o6wiE66ubk12fuLE6SPH0JD6Z8h9FHf+2cIfWT/dJ++99G+ifr3oJGVSpx0S0RERFqPAQsRERFpPQYsD2FhYYHw8HD5pz7S9/4ZQh/1vX+G0Ef2T/fpex8ttKB/ejPploiIiPQXR1iIiIhI6zFgISIiIq3HgIWIiIi0HgMWIiIi0noMWB4iKioKHh4esLS0RK9evXDkyBFomz/96U9yd9/qDx8fn6rnS0pKMG3aNDg6OsLW1hajR49GRkZGjfdISUnB8OHDYW1tjTZt2mDu3LmoqKioUWfv3r0ICgqSs8S9vLzw5ZdfNkl/fv31Vzz77LNy10PRl61bt9Z4XswTX7x4Mdq2bQsrKysMHToU58+fr1EnJycHEydOlBsctWjRAlOnTkVhYWGNOidOnMCAAQPkuRU7OH7yySf3tGXjxo3y/6Wo4+fnhx07djRLH1966aV7zulTTz2lM32MiIhAz5495c7T4vM0cuRInD17tkad5vxcNvb3uC79Gzx48D3n8NVXX9WJ/glr1qxB9+7dqzYK69OnD3744Qe9OH916Z+un7+7LVmyRPZh9uzZunsOxSohql1MTIzG3Nxc849//EOTnJysefnllzUtWrTQZGRkaLRJeHi4plu3bpobN25UPbKysqqef/XVVzXu7u6a2NhYzbFjxzS9e/fW9O3bt+r5iooKja+vr2bo0KGahIQEzY4dOzROTk6a+fPnV9W5dOmSxtraWjNnzhzNqVOnNKtXr9aYmJhodu7c2ej9ET//3Xff1WzevFmsYNNs2bKlxvNLlizRODg4aLZu3ao5fvy45rnnntN07NhRc/v27ao6Tz31lMbf319z+PBhzb59+zReXl6asLCwqufz8vI0zs7OmokTJ2qSkpI069ev11hZWWn++te/VtU5cOCA7OMnn3wi+7xw4UKNmZmZ5uTJk03ex8mTJ8s+VD+nOTk5Nepocx9DQ0M1X3zxhfy5iYmJmmHDhmnat2+vKSwsbPbPZVN8j+vSv0GDBsmfVf0cinOiC/0Ttm3bpvn+++81586d05w9e1azYMEC+dkQfdb181eX/un6+avuyJEjGg8PD0337t01s2bNqjqua+eQAcsDhISEaKZNm1ZVVqlUmnbt2mkiIiI02hawiAtXbXJzc+WXcOPGjVXHTp8+LS+Shw4dkmXxITQ2Ntakp6dX1VmzZo3G3t5eU1paKstvv/22DIqqGzdunPyHuyndfTFXq9UaFxcXzdKlS2v00cLCQl6QBfGlEa87evRoVZ0ffvhBY2RkpElLS5Plv/zlL5qWLVtW9U945513NJ07d64qjx07VjN8+PAa7enVq5fmj3/8Y5P2sTJgGTFixH1fo2t9zMzMlO395Zdfmv1z2Rzf47v7V3nBq35xuJsu9a+S+Dz97W9/07vzd3f/9On8FRQUaLy9vTW7du2q0SddPIdMCd1HWVkZ4uLiZLqh+v2KRPnQoUPQNiIlItILnp6eMk0ghvEE0Yfy8vIa/RDD/+3bt6/qh/hTpAKcnZ2r6oSGhsqbXSUnJ1fVqf4elXWa+//F5cuXkZ6eXqMt4h4UYoixen9EiiQ4OLiqjqgvzt9vv/1WVWfgwIEwNzev0R8xrH/r1i2t6LMYZhVDsJ07d8Zrr72GmzdvVj2na33My8uTf7Zq1apZP5fN9T2+u3+VvvrqKzg5OcHX1xfz589HcXFx1XO61D+VSoWYmBgUFRXJ1Im+nb+7+6dP52/atGkypXN3O3TxHOrNzQ8bW3Z2tvwQVz9RgiifOXMG2kRcrEXOUFzYbty4gffee0/OW0hKSpIXd3HBEhe3u/shnhPEn7X1s/K5B9URH9zbt2/LuSTNobI9tbWlelvFhb46U1NTeTGpXqdjx473vEflcy1btrxvnyvfoymJ+SqjRo2Sbbx48SIWLFiAp59+Wn7BTUxMdKqP4k7qIm/er18/+Q9/5c9vjs+lCMya+ntcW/+ECRMmoEOHDvIXCTGX6J133pHB4ubNm3WmfydPnpQXcDHXQcxx2LJlC7p27YrExES9OH/365++nL+YmBjEx8fj6NGj9zyni99BBix6QFzIKolJZCKAEV+0r7/+utkCCWpc48ePr/q7+A1HnNfHHntMjroMGTIEukT8hieC5/3790Mf3a9/r7zySo1zKCaJi3MnAlBxLnWB+CVIBCdiBGnTpk2YPHkyfvnlF+iL+/VPBC26fv5SU1Mxa9Ys7Nq1S0501QdMCd2HGAYUv8nePWNalF1cXKDNRMTcqVMnXLhwQbZVDMnl5ubetx/iz9r6Wfncg+qI2fXNGRRVtudB50X8mZmZWeN5MatdrKppjD4rcf5Fqk98JsU51aU+Tp8+Hdu3b8eePXvg5uZWdby5PpdN/T2+X/9qI36REKqfQ23vn/gNXKz66NGjh1wZ5e/vj5UrV+rN+btf//Th/MXFxcl/I8TqHTH6Kh4iGFu1apX8uxjh0LVzyIDlAR9k8SGOjY2tMfQrytVznNpILG0VvwWI3whEH8zMzGr0Qwxrijkulf0Qf4qh0eoXQBGViw9c5fCoqFP9PSrrNPf/C5HiEB/y6m0RQ49i3kb1/ogvofjCVtq9e7c8f5X/6Ig6YmmxyOFW74/4jUukSrSpz8K1a9fkHBZxTnWhj2IusbiYiyF20a67U1PN9blsqu/xw/pXG/GbvFD9HGpr/+5HvHdpaanOn7+H9U8fzt+QIUNk+0S7Kx9izpuY41j5d507h/WecmxAxFIssfrkyy+/lKsyXnnlFbkUq/qMaW3w5ptvavbu3au5fPmyXKYqlqCJpWdi5ULl0jWx5HL37t1y6VqfPn3k4+6la08++aRcoimWo7Vu3brWpWtz586VM8mjoqKabFmzmNUultCJh/iIfvrpp/LvV69erVrWLM7Dt99+qzlx4oRcTVPbsubAwEDNb7/9ptm/f7+cJV99ya+YIS+W/L744otyGaM416J/dy/5NTU11Sxbtkz2WazGaqxlzQ/qo3jurbfekjP1xTn9+eefNUFBQbIPJSUlOtHH1157TS49F5/L6stCi4uLq+o01+eyKb7HD+vfhQsXNO+//77slziH4rPq6empGThwoE70T5g3b55c9STaL75noixWof300086f/4e1j99OH+1uXvlk66dQwYsDyHWlIsTKtaQi6VZYs8LbSOWkLVt21a20dXVVZbFF66SuJC//vrrcsme+GA9//zz8h/X6q5cuaJ5+umn5T4dItgRQVB5eXmNOnv27NEEBATInyO+vGIfiqYgfo64iN/9EEt9K5c2L1q0SF6MxZdgyJAhch+F6m7evCkv3ra2tnIJ3pQpU2QgUJ3Yw6V///7yPcT/NxEI3e3rr7/WdOrUSfZZLN0T+zY0dR/FRU/8AyH+YRDBQ4cOHeS+BXd/ubW5j7X1TTyqf2aa83PZ2N/jh/UvJSVFXtxatWol/9+LPXLEP+jV9/HQ5v4Jf/jDH+RnT7yn+CyK71llsKLr5+9h/dOH81eXgEXXzqGR+E/DBpyIiIiImgfnsBAREZHWY8BCREREWo8BCxEREWk9BixERESk9RiwEBERkdZjwEJERERajwELERERaT0GLERERKT1GLAQERGR1mPAQkRERFqPAQsRERFpPQYsREREBG33/1r4RkQF2dtnAAAAAElFTkSuQmCC",
            "text/plain": [
              "<Figure size 640x480 with 1 Axes>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "x=np.arange(1, 40000)\n",
        "plt.plot(x, x * (4000 ** (-1.5)))"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "63402af1",
      "metadata": {
        "id": "63402af1"
      },
      "source": [
        "# Warmup技术"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 31,
      "id": "36aef5d6",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 449
        },
        "id": "36aef5d6",
        "outputId": "70f00d93-b6d9-4c42-eb1b-ccdb432cc3c9"
      },
      "outputs": [
        {
          "data": {
            "image/png": "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",
            "text/plain": [
              "<Figure size 640x480 with 1 Axes>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "# NoamDecayScheduler 是一个自定义或外部定义的学习率衰减调度器类。它需要接收配置 config 作为参数，可能实现了特定的学习率衰减方案\n",
        "class NoamDecayScheduler:\n",
        "    def __init__(self, config):\n",
        "        self.d_model = config[\"d_model\"]  # 获取模型的维度大小\n",
        "        self.warmup_steps = config[\"warmup_steps\"]  # 获取预热步数\n",
        "\n",
        "    def __call__(self, step):\n",
        "        step += 1  # 步数从1开始计算，而不是0\n",
        "        arg1 = step ** (-0.5)  # 4000步之后是arg1，计算步数的-0.5次方\n",
        "        arg2 = step * (self.warmup_steps ** (-1.5))  # 4000步之前是arg2，计算步数乘以预热步数的-1.5次方\n",
        "\n",
        "        arg3 = self.d_model ** (-0.5)  # 计算模型维度的-0.5次方\n",
        "\n",
        "        return arg3 * np.minimum(arg1, arg2)  # 返回学习率，取arg1和arg2的较小值乘以arg3\n",
        "\n",
        "\n",
        "temp_learning_rate_schedule = NoamDecayScheduler({\"d_model\": 512, \"warmup_steps\": 4000})  # 创建学习率调度器实例，设置模型维度为512，预热步数为4000\n",
        "#下面是学习率的设计图\n",
        "plt.plot(temp_learning_rate_schedule(np.arange(0, 40000)))  # 绘制学习率曲线，横轴为0到40000的步数\n",
        "plt.ylabel(\"Leraning rate\")  # 设置y轴标签为\"学习率\"\n",
        "plt.xlabel(\"Train step\")  # 设置x轴标签为\"训练步数\"\n",
        "plt.grid()  # 显示网格线\n",
        "plt.show()  # 显示图表\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 32,
      "id": "f94aa6ef",
      "metadata": {
        "id": "f94aa6ef"
      },
      "outputs": [],
      "source": [
        "from torch.optim.lr_scheduler import LambdaLR\n",
        "from torch.optim import Adam\n",
        "\n",
        "def get_optimizer(model, config):\n",
        "    base_lr = config['base_lr']\n",
        "    beta1 = config[\"beta1\"] # Adam 的 beta1\n",
        "    beta2 = config[\"beta2\"] # Adam 的 beta2\n",
        "    eps = config[\"eps\"] # Adam 的 eps，防止分母为0\n",
        "    optimizer = Adam(model.parameters(), lr=base_lr, betas=(beta1, beta2), eps=eps)\n",
        "    lr_scheduler1 = NoamDecayScheduler(config) #config是一个字典，包含了学习率衰减的参数\n",
        "    # 使用 LambdaLR 调度器，它可以根据给定的函数 lr_lambda 调整学习率。这里将 lr_scheduler 作为函数传递给 LambdaLR，它包含了特定于模型或任务的学习率调度规则\n",
        "    scheduler = LambdaLR(optimizer, lr_lambda=lr_scheduler1)\n",
        "    return optimizer, scheduler"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "0505aea6",
      "metadata": {
        "id": "0505aea6"
      },
      "source": [
        "# 保存模型，早停"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 33,
      "id": "486fb390",
      "metadata": {
        "id": "486fb390"
      },
      "outputs": [],
      "source": [
        "class SaveCheckpointsCallback:\n",
        "    def __init__(self, save_dir, save_step=5000, save_best_only=True):\n",
        "        \"\"\"\n",
        "        Save checkpoints each save_epoch epoch.\n",
        "        We save checkpoint by epoch in this implementation.\n",
        "        Usually, training scripts with pytorch evaluating model and save checkpoint by step.\n",
        "\n",
        "        Args:\n",
        "            save_dir (str): dir to save checkpoint\n",
        "            save_epoch (int, optional): the frequency to save checkpoint. Defaults to 1.\n",
        "            save_best_only (bool, optional): If True, only save the best model or save each model at every epoch.\n",
        "        \"\"\"\n",
        "        self.save_dir = save_dir\n",
        "        self.save_step = save_step\n",
        "        self.save_best_only = save_best_only\n",
        "        self.best_metrics = - np.inf\n",
        "\n",
        "        # mkdir\n",
        "        if not os.path.exists(self.save_dir):\n",
        "            os.mkdir(self.save_dir)\n",
        "\n",
        "    def __call__(self, step, state_dict, metric=None):\n",
        "        if step % self.save_step > 0:\n",
        "            return\n",
        "\n",
        "        if self.save_best_only:\n",
        "            assert metric is not None\n",
        "            if metric >= self.best_metrics:\n",
        "                # save checkpoints\n",
        "                torch.save(state_dict, os.path.join(self.save_dir, \"best.ckpt\"))\n",
        "                # update best metrics\n",
        "                self.best_metrics = metric\n",
        "        else:\n",
        "            torch.save(state_dict, os.path.join(self.save_dir, f\"{step}.ckpt\"))\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 34,
      "id": "ba9e24af",
      "metadata": {
        "id": "ba9e24af"
      },
      "outputs": [],
      "source": [
        "class EarlyStopCallback:\n",
        "    def __init__(self, patience=5, min_delta=0.01):\n",
        "        \"\"\"\n",
        "\n",
        "        Args:\n",
        "            patience (int, optional): Number of epochs with no improvement after which training will be stopped.. Defaults to 5.\n",
        "            min_delta (float, optional): Minimum change in the monitored quantity to qualify as an improvement, i.e. an absolute\n",
        "                change of less than min_delta, will count as no improvement. Defaults to 0.01.\n",
        "        \"\"\"\n",
        "        self.patience = patience\n",
        "        self.min_delta = min_delta\n",
        "        self.best_metric = - np.inf\n",
        "        self.counter = 0\n",
        "\n",
        "    def __call__(self, metric):\n",
        "        if metric >= self.best_metric + self.min_delta:\n",
        "            # update best metric\n",
        "            self.best_metric = metric\n",
        "            # reset counter\n",
        "            self.counter = 0\n",
        "        else:\n",
        "            self.counter += 1\n",
        "\n",
        "    @property\n",
        "    def early_stop(self):\n",
        "        return self.counter >= self.patience\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "3b3dc4fb",
      "metadata": {
        "id": "3b3dc4fb"
      },
      "source": [
        "# 评估，训练"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 35,
      "id": "7d854676",
      "metadata": {
        "id": "7d854676"
      },
      "outputs": [],
      "source": [
        "@torch.no_grad()\n",
        "def evaluating(model, dataloader, loss_fct):\n",
        "    loss_list = []\n",
        "    for batch in dataloader:\n",
        "        encoder_inputs = batch[\"encoder_inputs\"]\n",
        "        encoder_inputs_mask = batch[\"encoder_inputs_mask\"]\n",
        "        decoder_inputs = batch[\"decoder_inputs\"]\n",
        "        decoder_labels = batch[\"decoder_labels\"]\n",
        "        decoder_labels_mask = batch[\"decoder_labels_mask\"]\n",
        "\n",
        "        # 前向计算\n",
        "        outputs = model(\n",
        "            encoder_inputs,\n",
        "            decoder_inputs,\n",
        "            encoder_inputs_mask\n",
        "            )\n",
        "        logits = outputs.logits\n",
        "        loss = loss_fct(logits, decoder_labels, padding_mask=decoder_labels_mask)         # 验证集损失\n",
        "        loss_list.append(loss.cpu().item())\n",
        "\n",
        "    return np.mean(loss_list)\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 36,
      "id": "753f1655",
      "metadata": {
        "id": "753f1655"
      },
      "outputs": [],
      "source": [
        "# 训练\n",
        "def training(\n",
        "    model,\n",
        "    train_loader,\n",
        "    val_loader,\n",
        "    epoch,\n",
        "    loss_fct,\n",
        "    optimizer,\n",
        "    scheduler=None,\n",
        "    tensorboard_callback=None,\n",
        "    save_ckpt_callback=None,\n",
        "    early_stop_callback=None,\n",
        "    eval_step=500,\n",
        "    ):\n",
        "    record_dict = {\n",
        "        \"train\": [],\n",
        "        \"val\": []\n",
        "    }\n",
        "\n",
        "    global_step = 1\n",
        "    val_loss = 0\n",
        "    model.train()\n",
        "    with tqdm(total=epoch * len(train_loader)) as pbar:\n",
        "        for epoch_id in range(epoch):\n",
        "            # training\n",
        "            for batch in train_loader:\n",
        "                encoder_inputs = batch[\"encoder_inputs\"]\n",
        "                encoder_inputs_mask = batch[\"encoder_inputs_mask\"]\n",
        "                decoder_inputs = batch[\"decoder_inputs\"]\n",
        "                decoder_labels = batch[\"decoder_labels\"]\n",
        "                decoder_labels_mask = batch[\"decoder_labels_mask\"]\n",
        "                # 梯度清空\n",
        "                optimizer.zero_grad()\n",
        "\n",
        "                # 前向计算\n",
        "                outputs = model(\n",
        "                    encoder_inputs,\n",
        "                    decoder_inputs,\n",
        "                    encoder_inputs_mask\n",
        "                    )\n",
        "                logits = outputs.logits\n",
        "                loss = loss_fct(logits, decoder_labels, padding_mask=decoder_labels_mask)\n",
        "\n",
        "                # 梯度回传\n",
        "                loss.backward()\n",
        "\n",
        "                # 调整优化器，包括学习率的变动等\n",
        "                optimizer.step()\n",
        "                if scheduler is not None:\n",
        "                    scheduler.step() # 更新学习率,学习率就会传递给optimizer\n",
        "\n",
        "                loss = loss.cpu().item()\n",
        "                # record\n",
        "                record_dict[\"train\"].append({\n",
        "                    \"loss\": loss, \"step\": global_step\n",
        "                })\n",
        "\n",
        "                # evaluating\n",
        "                if global_step % eval_step == 0:\n",
        "                    model.eval()\n",
        "                    val_loss = evaluating(model, val_loader, loss_fct)\n",
        "                    record_dict[\"val\"].append({\n",
        "                        \"loss\": val_loss, \"step\": global_step\n",
        "                    })\n",
        "                    model.train()\n",
        "\n",
        "                    # 2. 保存模型权重 save model checkpoint\n",
        "                    if save_ckpt_callback is not None:\n",
        "                        save_ckpt_callback(global_step, model.state_dict(), metric=-val_loss)\n",
        "\n",
        "                    # 3. 早停 Early Stop\n",
        "                    if early_stop_callback is not None:\n",
        "                        early_stop_callback(-val_loss)\n",
        "                        if early_stop_callback.early_stop:\n",
        "                            print(f\"Early stop at epoch {epoch_id} / global_step {global_step}\")\n",
        "                            return record_dict\n",
        "\n",
        "                # udate step\n",
        "                global_step += 1\n",
        "                pbar.update(1)\n",
        "                pbar.set_postfix({\"epoch\": epoch_id, \"loss\": loss, \"val_loss\": val_loss})\n",
        "\n",
        "    return record_dict\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "17dd83e9",
      "metadata": {
        "id": "17dd83e9"
      },
      "source": [
        "# 开始训练"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 38,
      "id": "5ee7ed1b",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "5ee7ed1b",
        "outputId": "d94c349e-3a4d-40c0-ff4f-d363262a4044"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "save cache to wmt16\\.cache\\de2en_train_128.npy\n",
            "save cache to wmt16\\.cache\\de2en_val_128.npy\n"
          ]
        }
      ],
      "source": [
        "#模型的超参\n",
        "config = {\n",
        "    \"bos_idx\": 1,\n",
        "    \"eos_idx\": 3,\n",
        "    \"pad_idx\": 0,\n",
        "    \"vocab_size\": len(word2idx),\n",
        "    \"max_length\": 128,#seq_len最大长度\n",
        "    \"d_model\": 512,#可以调整\n",
        "    \"dim_feedforward\": 2048, # FFN 的隐藏层大小\n",
        "    \"dropout\": 0.1,#可以调整\n",
        "    \"layer_norm_eps\": 1e-6, # 层归一化的 epsilon, 防止除零错误\n",
        "    \"num_heads\": 8,#论文里是8，可以调整\n",
        "    \"num_decoder_layers\": 6, #论文是6，可以调整\n",
        "    \"num_encoder_layers\": 6, #论文是6，可以调整\n",
        "    \"label_smoothing\": 0.1,#标签平滑，防止过拟合\n",
        "    \"beta1\": 0.9, # Adam 的 beta1\n",
        "    \"beta2\": 0.98,\n",
        "    \"eps\": 1e-9, # Adam 的 epsilon\n",
        "    \"warmup_steps\": 4000,\n",
        "    \"share_embedding\": False, # 是否共享词向量，如果改为True，效果不好\n",
        "    \"base_lr\": 0.1,\n",
        "    }\n",
        "# 数据加载器\n",
        "def get_dl(dataset, batch_size, shuffle=True):\n",
        "    sampler = TransformerBatchSampler(dataset, batch_size=batch_size, shuffle_batch=shuffle)\n",
        "    sample_dl = DataLoader(dataset, batch_sampler=sampler, collate_fn=partial(collate_fct, tokenizer=tokenizer))\n",
        "    return sample_dl\n",
        "\n",
        "# dataset\n",
        "train_ds = LangPairDataset(\"train\", max_length=config[\"max_length\"])\n",
        "val_ds = LangPairDataset(\"val\", max_length=config[\"max_length\"])\n",
        "# tokenizer\n",
        "tokenizer = Tokenizer(word2idx=word2idx, idx2word=idx2word, max_length=config[\"max_length\"])\n",
        "batch_size = 4096\n",
        "# dataloader\n",
        "train_dl = get_dl(train_ds, batch_size=batch_size, shuffle=True)\n",
        "val_dl = get_dl(val_ds, batch_size=batch_size, shuffle=False)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 39,
      "id": "9da25003",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "9da25003",
        "outputId": "92d93710-2919-4315-b168-db8a1db18abd"
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "500"
            ]
          },
          "execution_count": 39,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "len(train_dl)*20"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 40,
      "id": "dfdfb28b",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 126,
          "referenced_widgets": [
            "7fff264309184763be76c74febde5af1",
            "a51848bc90674b5bbfe6aa10b1fbd92b",
            "f713cc5ab93e467699537e1033853259",
            "880ed6db148b41fe93ccf987173c95b0",
            "b0af4291ebd44162bc27b36c1ad3f651",
            "eac3d467f0e24fc5a461c4f5037d76da",
            "56b020a70cd34c1c9673d7ebdba23c43",
            "7d1e98340eb54ca7be701aba5cf76943",
            "d3ac645daf904649988e69aa58fb665a",
            "928f41cfb6184310afb07d861c17a413",
            "91c3e9b25c94440181ce6e679ef357c3"
          ]
        },
        "id": "dfdfb28b",
        "outputId": "ecce7e6d-015d-4228-8e1c-377a1851aebd"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "模型总参数量: 85,663,625\n"
          ]
        },
        {
          "data": {
            "application/vnd.jupyter.widget-view+json": {
              "model_id": "2fa777f5dd7b450a97a1f4fd8a1f21af",
              "version_major": 2,
              "version_minor": 0
            },
            "text/plain": [
              "  0%|          | 0/500 [00:00<?, ?it/s]"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "name": "stderr",
          "output_type": "stream",
          "text": [
            "C:\\Users\\41507\\AppData\\Roaming\\Python\\Python312\\site-packages\\torch\\nn\\_reduction.py:51: UserWarning: size_average and reduce args will be deprecated, please use reduction='none' instead.\n",
            "  warnings.warn(warning.format(ret))\n"
          ]
        },
        {
          "ename": "KeyboardInterrupt",
          "evalue": "",
          "output_type": "error",
          "traceback": [
            "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
            "\u001b[1;31mKeyboardInterrupt\u001b[0m                         Traceback (most recent call last)",
            "Cell \u001b[1;32mIn[40], line 29\u001b[0m\n\u001b[0;32m     25\u001b[0m early_stop_callback \u001b[38;5;241m=\u001b[39m EarlyStopCallback(patience\u001b[38;5;241m=\u001b[39m\u001b[38;5;241m8\u001b[39m)\n\u001b[0;32m     27\u001b[0m model \u001b[38;5;241m=\u001b[39m model\u001b[38;5;241m.\u001b[39mto(device)\n\u001b[1;32m---> 29\u001b[0m record \u001b[38;5;241m=\u001b[39m \u001b[43mtraining\u001b[49m\u001b[43m(\u001b[49m\n\u001b[0;32m     30\u001b[0m \u001b[43m    \u001b[49m\u001b[43mmodel\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m     31\u001b[0m \u001b[43m    \u001b[49m\u001b[43mtrain_dl\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m     32\u001b[0m \u001b[43m    \u001b[49m\u001b[43mval_dl\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m     33\u001b[0m \u001b[43m    \u001b[49m\u001b[43mepoch\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m     34\u001b[0m \u001b[43m    \u001b[49m\u001b[43mloss_fct\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m     35\u001b[0m \u001b[43m    \u001b[49m\u001b[43moptimizer\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m     36\u001b[0m \u001b[43m    \u001b[49m\u001b[43mscheduler\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m     37\u001b[0m \u001b[43m    \u001b[49m\u001b[43mtensorboard_callback\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mNone\u001b[39;49;00m\u001b[43m,\u001b[49m\n\u001b[0;32m     38\u001b[0m \u001b[43m    \u001b[49m\u001b[43msave_ckpt_callback\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43msave_ckpt_callback\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m     39\u001b[0m \u001b[43m    \u001b[49m\u001b[43mearly_stop_callback\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mNone\u001b[39;49;00m\u001b[43m,\u001b[49m\n\u001b[0;32m     40\u001b[0m \u001b[43m    \u001b[49m\u001b[43meval_step\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;241;43m500\u001b[39;49m\n\u001b[0;32m     41\u001b[0m \u001b[43m    \u001b[49m\u001b[43m)\u001b[49m\n",
            "Cell \u001b[1;32mIn[36], line 48\u001b[0m, in \u001b[0;36mtraining\u001b[1;34m(model, train_loader, val_loader, epoch, loss_fct, optimizer, scheduler, tensorboard_callback, save_ckpt_callback, early_stop_callback, eval_step)\u001b[0m\n\u001b[0;32m     45\u001b[0m loss\u001b[38;5;241m.\u001b[39mbackward()\n\u001b[0;32m     47\u001b[0m \u001b[38;5;66;03m# 调整优化器，包括学习率的变动等\u001b[39;00m\n\u001b[1;32m---> 48\u001b[0m \u001b[43moptimizer\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mstep\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m     49\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m scheduler \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[0;32m     50\u001b[0m     scheduler\u001b[38;5;241m.\u001b[39mstep() \u001b[38;5;66;03m# 更新学习率,学习率就会传递给optimizer\u001b[39;00m\n",
            "File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python312\\site-packages\\torch\\optim\\lr_scheduler.py:137\u001b[0m, in \u001b[0;36mLRScheduler.__init__.<locals>.patch_track_step_called.<locals>.wrap_step.<locals>.wrapper\u001b[1;34m(*args, **kwargs)\u001b[0m\n\u001b[0;32m    135\u001b[0m opt \u001b[38;5;241m=\u001b[39m opt_ref()\n\u001b[0;32m    136\u001b[0m opt\u001b[38;5;241m.\u001b[39m_opt_called \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mTrue\u001b[39;00m  \u001b[38;5;66;03m# type: ignore[union-attr]\u001b[39;00m\n\u001b[1;32m--> 137\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mfunc\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[38;5;21;43m__get__\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43mopt\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mopt\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[38;5;18;43m__class__\u001b[39;49m\u001b[43m)\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n",
            "File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python312\\site-packages\\torch\\optim\\optimizer.py:487\u001b[0m, in \u001b[0;36mOptimizer.profile_hook_step.<locals>.wrapper\u001b[1;34m(*args, **kwargs)\u001b[0m\n\u001b[0;32m    482\u001b[0m         \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[0;32m    483\u001b[0m             \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mRuntimeError\u001b[39;00m(\n\u001b[0;32m    484\u001b[0m                 \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mfunc\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m must return None or a tuple of (new_args, new_kwargs), but got \u001b[39m\u001b[38;5;132;01m{\u001b[39;00mresult\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m.\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m    485\u001b[0m             )\n\u001b[1;32m--> 487\u001b[0m out \u001b[38;5;241m=\u001b[39m \u001b[43mfunc\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m    488\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_optimizer_step_code()\n\u001b[0;32m    490\u001b[0m \u001b[38;5;66;03m# call optimizer step post hooks\u001b[39;00m\n",
            "File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python312\\site-packages\\torch\\optim\\optimizer.py:91\u001b[0m, in \u001b[0;36m_use_grad_for_differentiable.<locals>._use_grad\u001b[1;34m(self, *args, **kwargs)\u001b[0m\n\u001b[0;32m     89\u001b[0m     torch\u001b[38;5;241m.\u001b[39mset_grad_enabled(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mdefaults[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mdifferentiable\u001b[39m\u001b[38;5;124m\"\u001b[39m])\n\u001b[0;32m     90\u001b[0m     torch\u001b[38;5;241m.\u001b[39m_dynamo\u001b[38;5;241m.\u001b[39mgraph_break()\n\u001b[1;32m---> 91\u001b[0m     ret \u001b[38;5;241m=\u001b[39m \u001b[43mfunc\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m     92\u001b[0m \u001b[38;5;28;01mfinally\u001b[39;00m:\n\u001b[0;32m     93\u001b[0m     torch\u001b[38;5;241m.\u001b[39m_dynamo\u001b[38;5;241m.\u001b[39mgraph_break()\n",
            "File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python312\\site-packages\\torch\\optim\\adam.py:223\u001b[0m, in \u001b[0;36mAdam.step\u001b[1;34m(self, closure)\u001b[0m\n\u001b[0;32m    211\u001b[0m     beta1, beta2 \u001b[38;5;241m=\u001b[39m group[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mbetas\u001b[39m\u001b[38;5;124m\"\u001b[39m]\n\u001b[0;32m    213\u001b[0m     has_complex \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_init_group(\n\u001b[0;32m    214\u001b[0m         group,\n\u001b[0;32m    215\u001b[0m         params_with_grad,\n\u001b[1;32m   (...)\u001b[0m\n\u001b[0;32m    220\u001b[0m         state_steps,\n\u001b[0;32m    221\u001b[0m     )\n\u001b[1;32m--> 223\u001b[0m     \u001b[43madam\u001b[49m\u001b[43m(\u001b[49m\n\u001b[0;32m    224\u001b[0m \u001b[43m        \u001b[49m\u001b[43mparams_with_grad\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    225\u001b[0m \u001b[43m        \u001b[49m\u001b[43mgrads\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    226\u001b[0m \u001b[43m        \u001b[49m\u001b[43mexp_avgs\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    227\u001b[0m \u001b[43m        \u001b[49m\u001b[43mexp_avg_sqs\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    228\u001b[0m \u001b[43m        \u001b[49m\u001b[43mmax_exp_avg_sqs\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    229\u001b[0m \u001b[43m        \u001b[49m\u001b[43mstate_steps\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    230\u001b[0m \u001b[43m        \u001b[49m\u001b[43mamsgrad\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mgroup\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mamsgrad\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m]\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    231\u001b[0m \u001b[43m        \u001b[49m\u001b[43mhas_complex\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mhas_complex\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    232\u001b[0m \u001b[43m        \u001b[49m\u001b[43mbeta1\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mbeta1\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    233\u001b[0m \u001b[43m        \u001b[49m\u001b[43mbeta2\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mbeta2\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    234\u001b[0m \u001b[43m        \u001b[49m\u001b[43mlr\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mgroup\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mlr\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m]\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    235\u001b[0m \u001b[43m        \u001b[49m\u001b[43mweight_decay\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mgroup\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mweight_decay\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m]\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    236\u001b[0m \u001b[43m        \u001b[49m\u001b[43meps\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mgroup\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43meps\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m]\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    237\u001b[0m \u001b[43m        \u001b[49m\u001b[43mmaximize\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mgroup\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mmaximize\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m]\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    238\u001b[0m \u001b[43m        \u001b[49m\u001b[43mforeach\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mgroup\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mforeach\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m]\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    239\u001b[0m \u001b[43m        \u001b[49m\u001b[43mcapturable\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mgroup\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mcapturable\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m]\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    240\u001b[0m \u001b[43m        \u001b[49m\u001b[43mdifferentiable\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mgroup\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mdifferentiable\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m]\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    241\u001b[0m \u001b[43m        \u001b[49m\u001b[43mfused\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mgroup\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mfused\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m]\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    242\u001b[0m \u001b[43m        \u001b[49m\u001b[43mgrad_scale\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43mgetattr\u001b[39;49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mgrad_scale\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43;01mNone\u001b[39;49;00m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    243\u001b[0m \u001b[43m        \u001b[49m\u001b[43mfound_inf\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43mgetattr\u001b[39;49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mfound_inf\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43;01mNone\u001b[39;49;00m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    244\u001b[0m \u001b[43m    \u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m    246\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m loss\n",
            "File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python312\\site-packages\\torch\\optim\\optimizer.py:154\u001b[0m, in \u001b[0;36m_disable_dynamo_if_unsupported.<locals>.wrapper.<locals>.maybe_fallback\u001b[1;34m(*args, **kwargs)\u001b[0m\n\u001b[0;32m    152\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m disabled_func(\u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n\u001b[0;32m    153\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m--> 154\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mfunc\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n",
            "File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python312\\site-packages\\torch\\optim\\adam.py:784\u001b[0m, in \u001b[0;36madam\u001b[1;34m(params, grads, exp_avgs, exp_avg_sqs, max_exp_avg_sqs, state_steps, foreach, capturable, differentiable, fused, grad_scale, found_inf, has_complex, amsgrad, beta1, beta2, lr, weight_decay, eps, maximize)\u001b[0m\n\u001b[0;32m    781\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[0;32m    782\u001b[0m     func \u001b[38;5;241m=\u001b[39m _single_tensor_adam\n\u001b[1;32m--> 784\u001b[0m \u001b[43mfunc\u001b[49m\u001b[43m(\u001b[49m\n\u001b[0;32m    785\u001b[0m \u001b[43m    \u001b[49m\u001b[43mparams\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    786\u001b[0m \u001b[43m    \u001b[49m\u001b[43mgrads\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    787\u001b[0m \u001b[43m    \u001b[49m\u001b[43mexp_avgs\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    788\u001b[0m \u001b[43m    \u001b[49m\u001b[43mexp_avg_sqs\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    789\u001b[0m \u001b[43m    \u001b[49m\u001b[43mmax_exp_avg_sqs\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    790\u001b[0m \u001b[43m    \u001b[49m\u001b[43mstate_steps\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    791\u001b[0m \u001b[43m    \u001b[49m\u001b[43mamsgrad\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mamsgrad\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    792\u001b[0m \u001b[43m    \u001b[49m\u001b[43mhas_complex\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mhas_complex\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    793\u001b[0m \u001b[43m    \u001b[49m\u001b[43mbeta1\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mbeta1\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    794\u001b[0m \u001b[43m    \u001b[49m\u001b[43mbeta2\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mbeta2\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    795\u001b[0m \u001b[43m    \u001b[49m\u001b[43mlr\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mlr\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    796\u001b[0m \u001b[43m    \u001b[49m\u001b[43mweight_decay\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mweight_decay\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    797\u001b[0m \u001b[43m    \u001b[49m\u001b[43meps\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43meps\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    798\u001b[0m \u001b[43m    \u001b[49m\u001b[43mmaximize\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mmaximize\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    799\u001b[0m \u001b[43m    \u001b[49m\u001b[43mcapturable\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mcapturable\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    800\u001b[0m \u001b[43m    \u001b[49m\u001b[43mdifferentiable\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mdifferentiable\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    801\u001b[0m \u001b[43m    \u001b[49m\u001b[43mgrad_scale\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mgrad_scale\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    802\u001b[0m \u001b[43m    \u001b[49m\u001b[43mfound_inf\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mfound_inf\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    803\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\n",
            "File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python312\\site-packages\\torch\\optim\\adam.py:379\u001b[0m, in \u001b[0;36m_single_tensor_adam\u001b[1;34m(params, grads, exp_avgs, exp_avg_sqs, max_exp_avg_sqs, state_steps, grad_scale, found_inf, amsgrad, has_complex, beta1, beta2, lr, weight_decay, eps, maximize, capturable, differentiable)\u001b[0m\n\u001b[0;32m    377\u001b[0m \u001b[38;5;66;03m# Decay the first and second moment running average coefficient\u001b[39;00m\n\u001b[0;32m    378\u001b[0m exp_avg\u001b[38;5;241m.\u001b[39mlerp_(grad, \u001b[38;5;241m1\u001b[39m \u001b[38;5;241m-\u001b[39m beta1)\n\u001b[1;32m--> 379\u001b[0m \u001b[43mexp_avg_sq\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mmul_\u001b[49m\u001b[43m(\u001b[49m\u001b[43mbeta2\u001b[49m\u001b[43m)\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43maddcmul_\u001b[49m\u001b[43m(\u001b[49m\u001b[43mgrad\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mgrad\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mconj\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mvalue\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;241;43m1\u001b[39;49m\u001b[43m \u001b[49m\u001b[38;5;241;43m-\u001b[39;49m\u001b[43m \u001b[49m\u001b[43mbeta2\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m    381\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m capturable \u001b[38;5;129;01mor\u001b[39;00m differentiable:\n\u001b[0;32m    382\u001b[0m     step \u001b[38;5;241m=\u001b[39m step_t\n",
            "\u001b[1;31mKeyboardInterrupt\u001b[0m: "
          ]
        }
      ],
      "source": [
        "\n",
        "epoch = 20\n",
        "\n",
        "# model\n",
        "model = TransformerModel(config)\n",
        "# 计算模型参数量\n",
        "def count_parameters(model):\n",
        "    return sum(p.numel() for p in model.parameters() if p.requires_grad)\n",
        "\n",
        "total_params = count_parameters(model)\n",
        "print(f\"模型总参数量: {total_params:,}\")\n",
        "\n",
        "\n",
        "\n",
        "# 1. 定义损失函数 采用交叉熵损失\n",
        "loss_fct = CrossEntropyWithPadding(config)\n",
        "# 2. 定义优化器 采用 adam\n",
        "# Optimizers specified in the torch.optim package\n",
        "optimizer, scheduler = get_optimizer(model, config)\n",
        "\n",
        "if not os.path.exists(\"checkpoints\"):\n",
        "    os.makedirs(\"checkpoints\")\n",
        "save_ckpt_callback = SaveCheckpointsCallback(\n",
        "    f\"checkpoints\", save_step=500, save_best_only=True)\n",
        "# 3. early stop\n",
        "early_stop_callback = EarlyStopCallback(patience=8)\n",
        "\n",
        "model = model.to(device)\n",
        "\n",
        "record = training(\n",
        "    model,\n",
        "    train_dl,\n",
        "    val_dl,\n",
        "    epoch,\n",
        "    loss_fct,\n",
        "    optimizer,\n",
        "    scheduler,\n",
        "    tensorboard_callback=None,\n",
        "    save_ckpt_callback=save_ckpt_callback,\n",
        "    early_stop_callback=None,\n",
        "    eval_step=500\n",
        "    )"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "xeEbSABIGmp5",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 446,
          "referenced_widgets": [
            "381277e910d647b98475c7e514d4ce59",
            "79e7a2f67e704862b46c4479a28aa57e",
            "530f7729ef174321868689c813cbab16",
            "6ceb216821134bffaacd542be9332afd",
            "b4f510c9bb9144ccb2fb6381ad2959b1",
            "260f33f2bfc745cf904790692b45daa3",
            "3a96896a8b1746b08d855322fc274a7c",
            "da3d1cec9148455ea084b22d7209805e",
            "512ed7c39b0a49ed97c4ed9aa9cb47e9",
            "6ada793910ae47b0953f6be510d7d935",
            "7045995d4587482c8d87797846e13ad9"
          ]
        },
        "id": "xeEbSABIGmp5",
        "outputId": "1046eae4-1991-4ccd-cb69-49c54f825a4c"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "save cache to wmt16/.cache/de2en_test_128.npy\n"
          ]
        },
        {
          "data": {
            "application/vnd.jupyter.widget-view+json": {
              "model_id": "381277e910d647b98475c7e514d4ce59",
              "version_major": 2,
              "version_minor": 0
            },
            "text/plain": [
              "0it [00:00, ?it/s]"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "name": "stderr",
          "output_type": "stream",
          "text": [
            "/usr/local/lib/python3.11/dist-packages/nltk/translate/bleu_score.py:577: UserWarning: \n",
            "The hypothesis contains 0 counts of 4-gram overlaps.\n",
            "Therefore the BLEU score evaluates to 0, independently of\n",
            "how many N-gram overlaps of lower order it contains.\n",
            "Consider using lower n-gram order or use SmoothingFunction()\n",
            "  warnings.warn(_msg)\n",
            "/usr/local/lib/python3.11/dist-packages/nltk/translate/bleu_score.py:577: UserWarning: \n",
            "The hypothesis contains 0 counts of 3-gram overlaps.\n",
            "Therefore the BLEU score evaluates to 0, independently of\n",
            "how many N-gram overlaps of lower order it contains.\n",
            "Consider using lower n-gram order or use SmoothingFunction()\n",
            "  warnings.warn(_msg)\n",
            "/usr/local/lib/python3.11/dist-packages/nltk/translate/bleu_score.py:577: UserWarning: \n",
            "The hypothesis contains 0 counts of 2-gram overlaps.\n",
            "Therefore the BLEU score evaluates to 0, independently of\n",
            "how many N-gram overlaps of lower order it contains.\n",
            "Consider using lower n-gram order or use SmoothingFunction()\n",
            "  warnings.warn(_msg)\n"
          ]
        },
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "testing loss: 3.5472568195799123\n"
          ]
        },
        {
          "data": {
            "text/plain": [
              "0.5363600692116299"
            ]
          },
          "execution_count": 49,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "from nltk.translate.bleu_score import sentence_bleu\n",
        "# load checkpoints\n",
        "model = TransformerModel(config) #初始化模型\n",
        "state_dict = torch.load(\"checkpoints/best.ckpt\")\n",
        "model.load_state_dict(state_dict)\n",
        "\n",
        "loss_fct = CrossEntropyWithPadding(config)\n",
        "# from dataset import LangPairDataset\n",
        "test_ds = LangPairDataset(\"test\", max_length=128, data_dir=\"./wmt16\")\n",
        "test_dl = DataLoader(test_ds, batch_size=1, collate_fn=partial(collate_fct, tokenizer=tokenizer))\n",
        "\n",
        "model = model.to(device)\n",
        "model.eval()\n",
        "collect = {}\n",
        "loss_collect = []\n",
        "\n",
        "predictions = []\n",
        "answers = []\n",
        "# 初始化BLEU分数列表\n",
        "bleu_scores = []\n",
        "for idx, batch in tqdm(enumerate(test_dl)):\n",
        "    encoder_inputs = batch[\"encoder_inputs\"]\n",
        "    encoder_inputs_mask = batch[\"encoder_inputs_mask\"]\n",
        "    decoder_inputs = batch[\"decoder_inputs\"]\n",
        "    decoder_labels = batch[\"decoder_labels\"]\n",
        "    # print(decoder_labels.cpu())\n",
        "    # decoder_labels1=tokenizer.decode(decoder_labels.cpu().numpy())\n",
        "    # print(decoder_labels1)\n",
        "    # 前向计算\n",
        "    outputs = model(\n",
        "        encoder_inputs,\n",
        "        decoder_inputs,\n",
        "        encoder_inputs_mask\n",
        "        )\n",
        "    loss = loss_fct(outputs.logits, decoder_labels)         # 测试集损失，如果batch_size不为1，需要加入mask\n",
        "\n",
        "    # print(outputs.logits.shape, decoder_labels.shape)\n",
        "\n",
        "    # loss = loss_fct(outputs.logits[:, :decoder_labels.shape[1]], decoder_labels)         # 验证集损失\n",
        "    # outputs = model.infer(encoder_inputs=encoder_inputs)\n",
        "    # print(outputs.logits.shape)\n",
        "    preds = outputs.logits.argmax(dim=-1) # 预测结果，[1,seq_len]\n",
        "    # print(preds.shape)\n",
        "    #把preds转为英文单词\n",
        "    preds = tokenizer.decode(preds.cpu().numpy()) #['预测句子']\n",
        "    # predictions.append(preds)\n",
        "    # print(preds)\n",
        "    #把decoder_labels转为英文单词\n",
        "    decoder_labels = tokenizer.decode(decoder_labels.cpu().numpy()) #['标签句子']\n",
        "    # answers.append(decoder_labels)\n",
        "    # print(decoder_labels)\n",
        "    belu=sentence_bleu([decoder_labels[0].split()],preds[0].split(),weights=(1, 0, 0, 0))\n",
        "    bleu_scores.append(belu)\n",
        "    collect[idx] = {\"loss\": loss.item(), \"src_inputs\": encoder_inputs, \"trg_inputs\": decoder_inputs, \"mask\": encoder_inputs_mask, \"trg_labels\": decoder_labels, \"preds\": preds}\n",
        "    loss_collect.append(loss.item())\n",
        "    # break\n",
        "\n",
        "# sort collect by value\n",
        "collect = sorted(collect.items(), key=lambda x: x[1][\"loss\"])\n",
        "print(f\"testing loss: {np.array(loss_collect).mean()}\")\n",
        "sum(bleu_scores) / len(bleu_scores)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "XQUq1g_zG5Q-",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "XQUq1g_zG5Q-",
        "outputId": "1a81cbee-8c8d-4aeb-b2a9-b476f7ccf2c9"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Requirement already satisfied: Cython in /usr/local/lib/python3.11/dist-packages (3.0.12)\n",
            "Collecting fastBPE\n",
            "  Downloading fastBPE-0.1.0.tar.gz (35 kB)\n",
            "  Preparing metadata (setup.py) ... \u001b[?25l\u001b[?25hdone\n",
            "Building wheels for collected packages: fastBPE\n",
            "  Building wheel for fastBPE (setup.py) ... \u001b[?25l\u001b[?25hdone\n",
            "  Created wheel for fastBPE: filename=fastBPE-0.1.0-cp311-cp311-linux_x86_64.whl size=809501 sha256=c74074a43301345f7c5b9464e8c7088372ac28490f6d6c03302f4d3e422905f6\n",
            "  Stored in directory: /root/.cache/pip/wheels/73/78/50/cd953038d211e114145aa29ed48c3ac825746309dd01929e74\n",
            "Successfully built fastBPE\n",
            "Installing collected packages: fastBPE\n",
            "Successfully installed fastBPE-0.1.0\n"
          ]
        }
      ],
      "source": [
        "!pip install Cython  # if failed to install fastBPE, try this line\n",
        "!pip install fastBPE #分词使用，分词直接在内存中进行，无需把数据写入文件，用subword-nmt命令"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "adzdtLeMGqCF",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 629,
          "referenced_widgets": [
            "3212f3a98f5e4a96ac888f368f4fff42",
            "8af2647d8486443a8a025bc30e9ddac6",
            "280b011dc683465985da449bc80ab71f",
            "16ae7acad596458890f112a68c515cdf",
            "f6971c6f2b22427cb2b58ffffda71135",
            "d939b58e958641bdb4f2a2accc1c3645",
            "5b30c15446eb4a6cbc62498fb6753323",
            "046c17ba17f94587968cda8c761c2bf7",
            "79a55387adba484e9485779a07bcc8e9",
            "ec9417d5c4e54d18966e0140e60e4f7e",
            "2d5c3abf516b48b6946778709ac9d97d"
          ]
        },
        "id": "adzdtLeMGqCF",
        "outputId": "a20404fb-2502-447d-cf41-7cdae9e86290"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "[['ein', 'mann', 'mit', 'einem', 'eimer', 'und', 'ein', 'mädchen', 'mit', 'einem', 'hut', 'am', 'strand', '.']]\n"
          ]
        },
        {
          "data": {
            "application/vnd.jupyter.widget-view+json": {
              "model_id": "3212f3a98f5e4a96ac888f368f4fff42",
              "version_major": 2,
              "version_minor": 0
            },
            "text/plain": [
              "  0%|          | 0/128 [00:00<?, ?it/s]"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "name": "stderr",
          "output_type": "stream",
          "text": [
            "/usr/local/lib/python3.11/dist-packages/IPython/core/pylabtools.py:151: UserWarning: There are no gridspecs with layoutgrids. Possibly did not call parent GridSpec with the \"figure\" keyword\n",
            "  fig.canvas.print_figure(bytes_io, **kw)\n"
          ]
        },
        {
          "data": {
            "image/png": "iVBORw0KGgoAAAANSUhEUgAAA0IAAAHkCAYAAAAThJ+uAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjAsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvlHJYcgAAAAlwSFlzAAAPYQAAD2EBqD+naQAAZD1JREFUeJzt3Xd4lGXe/v9zJmXSSAKhJGAgIKGG4oo0QUDZxYKryLLKIoodK3WRiKCxEB8sgGV1RQX0UdDHvquCigZFmpQAEqQEMFFBJEhCKAnJ3L8/+DI/xiRCkrkyuTPv13HMQabknE8u7plrPnM3h2VZlgAAAAAggDj9XQAAAAAA1DQaIQAAAAABh0YIAAAAQMChEQIAAAAQcGiEAAAAAAQcGiEAAAAAAYdGCAAAAEDAoRECAAAAEHBohAAAAAAEHBohAAAAAAGHRggAAABAwKERAgAAABBwaIQAAAAABJxgfxcAAACA2m379u368ssvtW/fPrndbq/7pk2b5qeqgOpxWJZl+bsIAAAA1E5z5szR7bffroYNGyo+Pl4Oh8Nzn8Ph0Lp16/xYHVB1NEIAAACoUIsWLXTHHXfo3nvv9XcpgE/RCAEAAKBC0dHRyszMVKtWrfxdCuBTHCwBAAAAFRo2bJg+/fRTf5cB+BwHSwAAAECFWrduralTp2rlypXq1KmTQkJCvO6/5557/FQZUD1sGgcAAIAKtWzZssL7HA6Hdu7cWYPVAL5DIwQAAAAg4LCPEAAAAE6ruLhYW7duVUlJib9LAXyCRggAAAAVOnLkiG666SZFRESoY8eOysnJkSTdfffdeuyxx/xcHVB1NEIAAACoUGpqqjZs2KCMjAyFhYV5bh84cKDefPNNP1YGVA9HjQMAAECF3n//fb355pvq2bOnHA6H5/aOHTsqOzvbj5UB1cMaIQAAAFTo119/VePGjcvcfvjwYa/GCLAbGiEAAABUqFu3bvroo4881082Py+99JJ69erlr7KAamPTOAAAAFRo+vTpuuSSS5SVlaWSkhLNnj1bWVlZWr58uZYuXerv8oAqY40QAAAAKtSnTx9lZmaqpKREnTp10qeffqrGjRtrxYoVOvfcc/1dHlBlnFAVAAAAQMBh0zgAAAD8IbfbrR07dmjfvn1yu91e911wwQV+qgqoHhohAAAAVGjlypX6xz/+oR9++EG/35DI4XCotLTUT5UB1cOmcQAAAKhQ165d1aZNG6WlpSkhIaHMIbNjYmL8VBkq8uGHH57xY//6178arKR2oxECAABAhSIjI7Vhwwa1bt3a36XgDDmd3sdDczgcXmvzTm1mA3mNHkeNAwAAtpOXl6c777xTHTp0UMOGDdWgQQOvC3ynR48e2rFjh7/LqJRAXz7cbrfn8umnn6pr16765JNPdPDgQR08eFAff/yx/vSnP2nRokX+LtWv2EcIAHyMnYq9MR4wYeTIkdqxY4duuukmNWnSpMzmWlVhWZZyc3PVuHFjhYWF+aBK+9q4caPn57vvvlsTJkzQ3r171alTJ4WEhHg9tnPnzjVd3mmZWD7sauzYsXrhhRfUp08fz22DBg1SRESEbr31Vm3ZssWP1fkXm8YBgA+xU7E3xgOm1KtXT8uWLVOXLl18lul2uxUWFqbNmzcrOTnZZ7l25HQ6y2xOdaqT99XW17GJ5cOuwsPD9e233yolJcXr9o0bN6pHjx46evSonyrzP9YIAYAPjR49Wt26ddNHH31U7k7FgYbxgCnt2rXz+Qc4p9Op5ORk5eXlBXwjtGvXLn+XUC0mlg+7Ou+88zR+/Hi99tpratKkiSTpl19+0T//+U91797dz9X5F2uETvGnP/2pUo93OBz68MMP1axZM0MVAbAbdir2FijjURfmj+3bt+vLL78sdxPGadOm+amqin377beaPHmypk2bppSUlDKba0VHR1cp9z//+Y9mzJih559/vsw36LAPU8uHHe3YsUNDhgzRtm3blJiYKEnKzc1VcnKy3n///Vr1/nzqJplnqkOHDgoOrtq6HdYInSIzM1MTJkxQVFTUaR9rWZYee+wxFRUV1UBlAOzi5E7FtWli8adAGQ+7zx9z5szR7bffroYNGyo+Pt5rzZ3D4aiVjVBsbKwKCgp04YUXet1e3c21rrvuOh05ckRdunRRaGiowsPDve4/cOBAlWu2q/T0dDVp0kQ33nij1+2vvPKKfv31V917771+qqxippYPO2rdurU2btyozz77TN9//70kqX379ho4cGCtW0vftWvXP9wk8/ecTqe2bdumVq1aVen5WCN0CqfTqb1796px48Zn9Ph69eppw4YNVR58AHXDqd9gZWdn6/7779c///lP2+xU7GuBOB52nz9atGihO+64o1Z+oK1I9+7dFRwcrDFjxpS7M3y/fv2qlDt//vw/vP/666+vUq6dJSUl6Y033lDv3r29bl+1apWuueaaWrkZnanlA2Y5nU6tXr1ajRo1Ou1jLctSSkqKNm7cSCPkCz/88IOaN29+xt1xbm6umjZtqqCgIMOVAajN7L5Tsa8F4njYff6Ijo5WZmZmrWnMzkRERITWr1+vtm3b+ruUOi8sLExbtmxRy5YtvW7fuXOnOnTooGPHjvmpsoqxfHhbsmSJlixZUu6mr6+88oqfqiprwIABeu+99xQbG3tGj7/00kv18ssvKyEhoUrPx6Zxp2jRokWlHn9yO0sAga02fhvqT4E4HnafP4YNG6ZPP/1Uo0eP9ncpZ6xbt27Kzc018kE3Oztbc+fOVXZ2tmbPnq3GjRvrk08+UfPmzdWxY0efP19tl5iYqG+++aZMI/TNN9+oadOmfqrqj5lcPuwmLS1NDz30kLp161brD1rz5ZdfVurxH3/8cbWej0bod/bv36/Dhw97TWqbN2/WE088ocOHD+vKK6/UP/7xDz9WCKC2qeyH4LouUMfDzvNH69atNXXqVK1cubLcTRjvueceP1VWsbvvvltjxozx+WaXS5cu1SWXXKLzzz9fX331lR599FE1btxYGzZs0Msvv6y3337bF+Xbyi233KKxY8fq+PHjnn1ulixZokmTJmnChAl+rq58ppYPO3rhhRc0b948jRw50t+lVEtJSYmOHTt2Rvtinik2jfud4cOHq2nTpnryySclSfv27VO7du3UtGlTnX322frkk0/08ssv235hAmCGHXcqNimQxsPO88fvv+k/lcPh0M6dO2uwmjPjdDrL3OaLzS579eqlYcOGafz48V77cq1evVpXXXWVfvzxx+qWbjuWZWny5Ml6+umnVVxcLOnE5nL33ntvrTyQhmRu+bCjuLg4rV69Wmeffba/Szkj//nPf5SXl6dRo0Z5bnv00Uf18MMPq6SkRBdeeKHefPNN1a9fv9rPRSP0Oy1bttS8efM8O9E98cQTeuGFF/T9998rODhYTzzxhN5++22tXLnSz5UCqI3suFOxSYE0HswfNeuHH374w/urumYyKipKmzZtUsuWLb0aod27d6tdu3a1cn+YmlJYWKgtW7YoPDxcycnJcrlc/i6pQqaWDzu69957FRUVpalTp/q7lDMyYMAA/e1vf9Odd94pSVq+fLn69u2rhx56SO3bt9eUKVN0ySWX6Kmnnqr2c7Fp3O/s3btXSUlJnutffPGFrrrqKs/xyf/6178qPT3dT9UBqO327t1b7k6bjRo10p49e/xQkX8F0ngwf9QsUx9kY2NjtWfPnjJrydavX1+rzvvkD1FRUTrvvPP8XcYZCaRG53SOHTumF198UZ9//rk6d+5cZjNBXzQUvrR582avmt5++239+c9/1pQpUySdWBs5ZswYGiEToqOjdfDgQc8LaPXq1brppps89zscjlp17odTlZaWat68eRUeFeSLL76ocvbBgwe1evXqcnOvu+66KucCdY3JnYrt+Dq0407WVcX8UfNee+01vfDCC9q1a5dWrFihFi1aaNasWWrZsqWuuOKKKmVec801uvfee/V///d/cjgccrvd+uabbzRx4sRa+zoz4aqrrjrjx7777rsGK6k6E8uHHW3cuFFdu3aVJH333Xde99XGAyccOnRIcXFxnuvLli3TsGHDPNc7duyon3/+2SfPRSP0Oz179tTTTz+tOXPm6N1339WhQ4e8TsZ16ll5a5sxY8Zo3rx5uuyyy5SSkuKzhfs///mPRowYocLCQkVHR5c50V4gTQzA6Zjaqdiur0M77mRdVcwfNev555/XtGnTNHbsWD366KOefT5iY2M1a9asKn/QnT59uu68804lJiaqtLRUHTp0UGlpqf7xj3/o/vvv9+WfUKvFxMR4frYsS++9955iYmLUrVs3SdLatWt18ODBSjVMNcnU8mFHlT0Sm781a9ZMW7ZsUfPmzVVYWKgNGzZo5syZnvvz8vIUERHhmyez4GXDhg1Ww4YNrdDQUMvpdFr333+/1/3XXnutddttt/mpuj8WFxdnffTRRz7PTU5OtsaMGWMdPnzY59lAXeN2u61JkyZZYWFhltPptJxOpxUREWGlpaVVK9eur0NT41EbMX/UrPbt21vvvfeeZVmWFRUVZWVnZ1uWZVmbNm2y4uLiqp3/ww8/WB999JH15ptvWtu2bat2np1NmjTJuvnmm62SkhLPbSUlJdatt95qTZw40Y+VVcz08gFzJk+ebLVr18569dVXrWuuucZq3ry517L373//2zr//PN98lwcLKEc+/fv1zfffKP4+Hj16NHD676PPvpIHTp0+MMj7PhL06ZNlZGRoTZt2vg0NzIyUps2bbLVifYAf/P1TsV2fx3aaSfr6mD+qDnh4eH6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7u/yKtSyZUtr3bp1lmVZ1rnnnmu98MILlmVZ1uLFi6u1k928efOso0eP+qRGfzl69KjnSDfVPeLNihUrrJYtW3qWi1MvtXnnzlP5cjxM2rZtm9WnTx/P6/DU12NtHusdO3ZYU6ZMsa655hrPDrUff/yx9d1331U5086vQxPjUVuZnD8WL15s/eUvf/EcfMKXfD1/nPqe8vv3Gl+995gaj//+97/WoEGDjIyzZVnWb7/9Zi1evNh67bXXrPnz53tdqsPX49GyZUtr//79lmWdOJKer5aPmlg2TtZm6vWydOnSP7xU1bZt26xu3br5fM578803rVatWlnPPPOMtXz5cmvDhg1el9rm6NGjVu/eva2goCDr4osvtsaNG2eNHTvWGjRokBUUFGT16tXLZ/Mhm8b9gczMTK+TOJnYHMGXbr75ZiUmJuqBBx7Qc889p3/+8586//zztWbNGl111VV6+eWX/V1ijTpy5IgmTZqkt956S3l5eWXur+qOo127dlWbNm2UlpZW7nbHtXV/DVPjYdL555+v4OBgTZ48udyx9uV21L6ydOlSXXLJJTr//PP11VdfacuWLWrVqpUee+wxrVmzRm+//ba/S6xRgToeJuaP+vXr68iRIyopKVFERESZb4sPHDhQ5Wxfzx9BQUHas2ePGjduLKfTWe4359b/2++tqu89psbD5Dj/5z//0YgRI1RYWKjo6GivcXE4HNXK9nXds2fP1m233aawsDDdeOONatmypaZOnVrt5aMmlg3J7P9jeed4+/1+TlXRvXt3BQcHa8yYMeXun3ZyjVRlVVSvL8bZlOLi4nJPTn3NNddo3LhxcrlcPnkeGqEzVFxcrOLiYq/NUmobt9stt9vt2YfgzTff1DfffKPk5GSNHj26UqueGzRooG3btqlhw4aenRorUp03E5PuvPNOffnll3r44Yc1cuRIPffcc/rpp5/073//W4899phGjBhRpdzIyEht2LBBrVu39nHFZpkaD5MiIyO1du1atWvXzt+lnLFevXpp2LBhGj9+vNe29KtXr9ZVV12lH3/88Yyz6sLr0JfjYVe+mj/mz5//h/dX52Scvpw/pBMN8MkvMk49oWh5qvrhztR4mBznNm3a6NJLL9X06dMVERFR5ZzymKy7uLjY01BI1Vs+amLZkMyOR35+vtf148ePa/369Zo6daoeffTRKh8IJiIiQuvXr1fbtm2rXFt5fvjhhz+83y6bzJlAI1SOuXPnat26derZs6dGjBih++67T08++aRKSkp04YUXauHChYqLi/N3meU6duyYNm7cWGZ/CofDocsvv/yMc+bPn69rrrlGLpfL6JuJSc2bN9err76q/v37Kzo6WuvWrVPr1q312muvacGCBfr444+rlHvhhRdq0qRJuvjii31csVmmxsOk8847TzNnzjS207IJUVFR2rRpk1q2bOn1wX/37t1q166d5xCmZ6IuvA59OR52wPxRuWxJ+utf/1qtbDuJjIzUpk2b1KpVK3+XUmmmlo+6tGwsXbpU48eP19q1a6v0+xdccIGmTZumgQMH+rSur776Sr179/Y62I504ohyy5cvr3X7Nq9evVrnnnuugoKCyr2/qKhIH3zwgf7+979X/8l8soFdHfLII49Y4eHh1sCBA60GDRpYo0ePtuLj463HHnvMmjFjhnXWWWdZo0eP9neZ5frkk0+shg0bltlvpbrblo4cOdJ6+eWXrR07dviwWvMiIyOtH374wbKsE2dVXrVqlWVZlrVz504rMjKyyrnvvvuu1aFDB2vu3LnWmjVrav22tieZGg+TlixZYvXq1cv68ssvrf3799tiv6ZmzZpZ33zzjWVZlhUVFWVlZ2dblnViuWnVqlWVc+36OjQ1HrWRifmjpvanMDV/nMxu1KiRT7JNjUdNjfOQIUOsN998s1oZp6rJ5cNX/4cmc2tqPCqyZcuWas2nb731lpHPF3Y7ce3v661Xr55n7rAsy9q7d6/P6qYR+p3WrVtbb7zxhmVZlvXtt99aTqfT60zhH3/8sdW8eXN/lfeHWrdubd1xxx3W3r17fZp78803W8nJyZbT6bTOOussa8SIEdacOXPKPTt2bdKpUycrIyPDsizLuuiii6wJEyZYlmVZs2fPtpo1a1bl3PLesO1wsART42HS78fWDgdLmDBhgtWnTx9rz549Vr169azt27dby5Yts1q1amU9+OCDVc616+vQ1HjURibmj1M/EPz+deDL14Op+cPX2abGo6bG+aWXXrKaN29uPfDAA9bbb79tffDBB16XyrL78uHr3Joaj983KJmZmdYnn3xi9evXzzr//POrnGvq84XD4bD27dtX5vatW7da9erVq3KuKQ6Hw6sROvVLNMs60Qg5HA7fPJdlsWncqVwul3bs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Oy4fJpc70+Nhp88XR44c8eR++umnuuqqq+R0OtWzZ8/THqChptXEe+mpfL/k2dg555yjvLy8M358r169lJOTU6nnSElJ0YYNGyRJPXr00IwZM/TNN9/ooYceqvYL8/rrr9ebb75ZrYzyWJaldevW6amnntJf//pXDRgwQP/7v/+rTp06VWv7XcnseNx888164403qpVRHpM123E87rjjDq1cuVKvvPKKli9f7nnzatWqlR599NFqZV999dW66aab9Oabbyo3N1e5ublauHChbr75Zg0fPrzKuSbHeeTIkXr++efL3P7iiy9qxIgRVc616+vQ1HjUNjUxf9xyyy0aM2aMVq1aJYfDoZ9//lmvv/66Jk6cqNtvv72yJXsxNX+YzDY1HibHuSL5+fnKz8+vVoYdlw+Ty53J8bDb54vWrVvr/fffV25urhYvXqy//OUvkqR9+/YpOjraJ7X7Sk28l56KNUKnsCxLU6dO9exMdjpVOYT2/fffr8OHD0s6sdPk4MGD1bdvX8XFxVX7zaC0tFQzZszQ4sWL1blz5zI7HT711FNVym3QoIEKCwvVpUsX9evXT7fccov69u2r2NjYatUr+X48xo8f7/nZ7XbrxRdf1Oeff+7T8TD5f2iX8Rg/frwefvhhRUZGej3H119/Xeax1fnW7IknnpDD4dB1113nWXsQEhKi22+/XY899liVc02Os8Ph0EsvvaRPP/1UPXv2lCStWrVKOTk5uu6666pcs11fh6bG448MHDhQO3fu1M6dO43kl6cm5o/JkyfL7Xbroosu0pEjR3TBBRfI5XJp4sSJuvvuuyuddypT84fJbFPjYXKcn376aa/rlmVpz549eu2113TJJZdUK9uOy4fJ5c7X42HnzxfTpk3TP/7xD40bN04XXXSRevXqJenE2qFzzjmnyrmnU5X34pp4Lz0V5xE6Rf/+/T1H5jhTb7zxhhISEqr1vAcOHFD9+vUr/dy/N2DAgArvczgc+uKLL6qU+9FHH6lv37419q1Bdcbjj8bgVNUZj/L46v/Q19mmxmPAgAF67733FBsba2y5O9WRI0eUnZ0tSTr77LPP+A2yMmrjOJ+K1+GZe+6557R//3498MADPs+uSE3OH8XFxdqxY4cKCwvVoUMHRUVFVTrj90y+jk2/R5gYD1O5vz9s88nDLl944YVKTU2t1ia/J9lp+aiJ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fL/vlz1H8bEzfixrhAAAAAAEHBohAAAAAAGHRggAAABAwKERAgAAABBwaIQAAAAABBwaIQAAAAABp8qNUP/+/eVwOORwOJSZmenDkuxVAwAAAAD7qdYaoVtuuUV79uxRSkqKdu/e7WlKfn9ZuXKl53eOHj2qBx54QG3atJHL5VLDhg01bNgwbd682Sv7yJEjSk1N1dlnn62wsDA1atRI/fr10wcffOB5zLvvvqvVq1dX508AAAAAEICqdULViIgIxcfHe932+eefq2NH7zPVxcXFSZKKioo0cOBA5eTk6Mknn1SPHj30yy+/KD09XT169NDnn3+unj17SpJGjx6tVatW6ZlnnlGHDh2Ul5en5cuXKy8vz5PboEEDFZg8aSIAAACAOqlajVB54uLiyjRHJ82aNUsrVqzQ+vXr1aVLF0lSixYt9M4776hHjx666aab9N1338nhcOjDDz/U7Nmzdemll0qSkpKSdO655/q6XAAAAAABqEYPlvDGG2/oz3/+s6cJ8hThdGrcuHHKysrShg0bJEnx8fH6+OOPdejQoWo/b1FRkQoKCrwuAACcDvMHANRdPm+EevfuraioKK/LSdu2bVP79u3L/b2Tt2/btk2S9OKLL2r58uWKi4vTeeedp3Hjxumbb76pUk3p6emKiYnxXBITE6uUAwAILMwfAFB3+bwRevPNN5WZmel1OZVlWWeUc8EFF2jnzp1asmSJ/va3v2nz5s3q27evHn744UrXlJqaqvz8fM8lNze30hkAgMDD/AEAdZfP9xFKTExU69aty72vTZs22rJlS7n3nby9TZs2nttCQkLUt29f9e3bV/fee68eeeQRPfTQQ7r33nsVGhp6xjW5XC65XK5K/BUAADB/AEBdVqP7CF1zzTX6/PPPPfsBneR2uzVz5kx16NChzP5Dp+rQoYNKSkp07Ngx06UCAAAAqMN8vkYoLy9Pe/fu9botNjZWYWFhGjdunD744ANdfvnlXofPnj59urZs2aLPP/9cDodD0omTpQ4fPlzdunVTXFycsrKydN9992nAgAGKjo72ddkAAAAAAojPG6GBAweWuW3BggW65pprFBYWpi+++ELTp0/Xfffdpx9++EH16tXTgAEDtHLlSqWkpHh+Z9CgQZo/f77uu+8+HTlyRE2bNtXgwYM1bdo0X5cMAAAAIMD4rBFKSko6owMhRERE6JFHHtEjjzzyh49LTU1Vamqqr8oDAAAAAI9q7SP0r3/9S1FRUdq0aZOv6qmUSy65RB07dvTLcwMAAACwryqvEXr99dd19OhRSVLz5s19VlBlvPTSS36vAQAAAID9VLkRatasmS/rsG0NAAAAAOzH5wdLsIOT+zKVWMcNPUGpmVw5DOUadoYn0QVsw3IbyjX13mGYofEoPGQot/BE7pme4PtUJ3/HfbTIpzV5BJn5m92l5s6WcaywxFi229DpMiyTJw85Yu4UH+5jhgo39JYmSaUGx6O0OMRcdpGZz1wlxw199pRUUmrofUlSaZGZ/8fSYt9/RiwtPlHrmbzHO6yqzAQ29+OPPyoxMdHfZQAA/Cg3N1dnnXVWpX6H+QMA7OFM3uMDshFyu936+eefVa9ePc95iypSUFCgxMRE5ebm+vz8RXbMtmPNJrPtWLPJbDvWbDKbmmtntmVZOnTokJo2bSqns3LfsDN/1L5cu2ZTs/2z7VizyezaUnNl3uMDctM4p9NZ6W8Bo6OjjZ3I1Y7ZdqzZZLYdazaZbceaTWZTc+3LjomJqVI+80ftzbVrNjXbP9uONZvMrg01n+l7vMmtZAEAAACgVqIRAgAAABBwaIROw+Vy6YEHHpDL5SLbYK5ds+1Ys8lsO9ZsMpua60Z2Vdn172XZqplsarZ/th1rNpltx5oD8mAJAAAAAAIba4QAAAAABBwaIQAAAAABh0YIAAAAQMChEQIAAAAQcGiEAAAAAAQcGiEAAAAAAYdGCAAAAEDAoRECAAAAEHD+Pwls7tAtjZp4AAAAAElFTkSuQmCC",
            "text/plain": [
              "<Figure size 1000x500 with 2 Axes>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/plain": [
              "['a man with a hat and a hat is on a beach with a beach.']"
            ]
          },
          "execution_count": 67,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "\n",
        "# 在 Windows 系统上并没有 sys/mman.h 文件，windows上无法安装fastBPE\n",
        "import re\n",
        "from fastBPE import fastBPE\n",
        "from sacremoses import MosesDetokenizer, MosesTokenizer\n",
        "\n",
        "# `MosesTokenizer` 和 `MosesDetokenizer` 是来自 `sacremoses` 库的工具，用于自然语言处理中的分词（Tokenization）和去标记化（Detokenization）。这些工具主要用于对文本进行预处理和后处理，通常在处理自然语言处理任务时会用到。\n",
        "#\n",
        "# ### MosesTokenizer：\n",
        "# - **作用**：将原始文本分割成单词和标点符号。\n",
        "# - **特点**：基于 Moses 翻译工具中使用的分词方法。\n",
        "# - **功能**：\n",
        "#   - 将句子分割成单词和标点符号。\n",
        "#   - 处理缩写、连字符、标点等特殊情况。\n",
        "#   - 对文本进行标记化，方便后续处理。\n",
        "#\n",
        "# ### MosesDetokenizer：\n",
        "# - **作用**：将分词后的文本重新组合成原始的句子。\n",
        "# - **特点**：用于对分词后的文本进行还原，使其恢复为可读的句子形式。\n",
        "# - **功能**：\n",
        "#   - 将分词后的单词和标点符号重新组合成句子。\n",
        "#   - 处理分词后的标点、缩写等情况，使得结果更加自然和可读。\n",
        "#\n",
        "# 这些工具通常在文本预处理和后处理过程中使用，对输入的文本进行标记化和去标记化，是一种常用的处理方式。在自然语言处理任务中，对文本进行正确的分词和还原是很重要的，而 `MosesTokenizer` 和 `MosesDetokenizer` 提供了方便、高效的工具来处理这些任务。\n",
        "\n",
        "class Translator:\n",
        "    def __init__(self, model, src_tokenizer, trg_tokenizer):\n",
        "        self.bpe = fastBPE(\"./wmt16/bpe.30000\", \"./wmt16/vocab\") #如果bpe.30000名字变了，这里要改\n",
        "        self.mose_tokenizer = MosesTokenizer(lang=\"es\") # 德语分词器，如果是其他语言，这里要改\n",
        "        self.mose_detokenizer = MosesDetokenizer(lang=\"en\") # 英语去标记化器，如果是其他语言，这里要改\n",
        "        self.model = model # 模型\n",
        "        self.model.eval() # 设置为评估模式\n",
        "        self.src_tokenizer = src_tokenizer # 源语言分词器\n",
        "        self.trg_tokenizer = trg_tokenizer # 目标语言分词器\n",
        "        self.pattern = re.compile(r'(@@ )|(@@ ?$)') # 正则表达式，用于去除分词器添加的特殊标记,匹配 @@ ?$​ 出现在字符串末尾，可选后跟一个空格（?表示0或1次）\n",
        "\n",
        "    def draw_attention_map(self, attn_scores, cross_attn_scores, src_words_list, trg_words_list):\n",
        "        \"\"\"绘制注意力热力图\n",
        "        attn_scores (numpy.ndarray): 表示自注意力机制（self-attention）分数。\n",
        "        cross_attn_scores (numpy.ndarray): 表示交叉注意力机制的注意力分数。\n",
        "        src_words_list (list): 源语言句子的单词列表。\n",
        "        trg_words_list (list): 目标语言句子的单词列表。\n",
        "        \"\"\"\n",
        "        assert len(attn_scores.shape) == 3, \"attn_scores shape should be \" \\\n",
        "            f\"[num heads, target sequence length, target sequence length], but got {attn_scores.shape}\"\n",
        "        attn_scores = attn_scores[:, :len(trg_words_list), :len(trg_words_list)]\n",
        "\n",
        "        assert len(cross_attn_scores.shape) == 3, \"attn_scores shape should be \" \\\n",
        "            f\"[num heads, target sequence length, source sequence length], but got {cross_attn_scores.shape}\"\n",
        "        cross_attn_scores = cross_attn_scores[:, :len(trg_words_list), :len(src_words_list)]\n",
        "\n",
        "        num_heads, trg_len, src_len = cross_attn_scores.shape\n",
        "\n",
        "        fig = plt.figure(figsize=(10, 5), constrained_layout=True) # constrained_layout=True 自动调整子图参数，使之填充整个图像区域\n",
        "        grid = plt.GridSpec(trg_len, trg_len + src_len, wspace=0.1, hspace=0.1)# wspace,hspace 控制子图之间的间距\n",
        "        #下面是attn_scores的热力图\n",
        "        self_map = fig.add_subplot(grid[:,:trg_len]) #  添加子图\n",
        "        self_map.matshow(attn_scores.mean(dim=0), cmap='viridis') # 绘制热力图，cmap表示颜色,dim=0表示对第0维求均值\n",
        "        self_map.set_yticks(range(trg_len), trg_words_list, fontsize=10)\n",
        "        self_map.set_xticks(range(trg_len), [\"[BOS]\"] + trg_words_list[:-1], rotation=90)\n",
        "        #下面是cross_attn_scores的热力图\n",
        "        cross_map = fig.add_subplot(grid[:, trg_len:])\n",
        "        cross_map.matshow(cross_attn_scores.mean(dim=0), cmap='viridis')\n",
        "        cross_map.set_yticks(range(trg_len), [], fontsize=6)\n",
        "        cross_map.set_xticks(range(src_len), src_words_list, rotation=90)\n",
        "\n",
        "        plt.show()\n",
        "\n",
        "    def draw_attention_maps(self, attn_scores, cross_attn_scores, src_words_list, trg_words_list, heads_list):\n",
        "        \"\"\"绘制注意力热力图\n",
        "\n",
        "        Args:\n",
        "            - scores (numpy.ndarray): shape = [source sequence length, target sequence length]\n",
        "        \"\"\"\n",
        "        assert len(attn_scores.shape) == 3, \"attn_scores shape should be \" \\\n",
        "            f\"[num heads, target sequence length, target sequence length], but got {attn_scores.shape}\"\n",
        "        attn_scores = attn_scores[:, :len(trg_words_list), :len(trg_words_list)]\n",
        "\n",
        "        assert len(cross_attn_scores.shape) == 3, \"attn_scores shape should be \" \\\n",
        "            f\"[num heads, target sequence length, source sequence length], but got {cross_attn_scores.shape}\"\n",
        "        cross_attn_scores = cross_attn_scores[:, :len(trg_words_list), :len(src_words_list)]\n",
        "        # cross_attn_scores = cross_attn_scores[:, :len(src_words_list), :len(src_words_list)]\n",
        "\n",
        "        num_heads, trg_len, src_len = cross_attn_scores.shape\n",
        "        fig, axes = plt.subplots(2, len(heads_list), figsize=(5 * len(heads_list), 10))\n",
        "        for i, heads_idx in enumerate(heads_list):\n",
        "            axes[0, i].matshow(attn_scores[heads_idx], cmap='viridis')\n",
        "            axes[0, i].set_yticks(range(trg_len), trg_words_list)\n",
        "            axes[0, i].set_xticks(range(trg_len), [\"[BOS]\"] + trg_words_list[:-1], rotation=90)\n",
        "            axes[0, i].set_title(f\"head {heads_idx}\")\n",
        "            axes[1, i].matshow(cross_attn_scores[heads_idx], cmap='viridis')\n",
        "            axes[1, i].set_yticks(range(trg_len), trg_words_list)\n",
        "            axes[1, i].set_xticks(range(src_len), src_words_list, rotation=90)\n",
        "            axes[1, i].set_title(f\"head {heads_idx}\")\n",
        "\n",
        "        plt.show()\n",
        "\n",
        "\n",
        "    def __call__(self, sentence_list, heads_list=None, layer_idx=-1):\n",
        "        # 将输入句子列表转换为小写，并使用 MosesTokenizer 进行分词处理。\n",
        "        sentence_list = [\" \".join(self.mose_tokenizer.tokenize(s.lower())) for s in sentence_list]\n",
        "        # 将分词后的结果进行 BPE 编码，得到 tokens_list。\n",
        "        tokens_list = [s.split() for s in self.bpe.apply(sentence_list)]\n",
        "        print(tokens_list)\n",
        "        # 使用 src_tokenizer 对 tokens_list 进行编码，同时添加起始标记 ([BOS]) 和结束标记 ([EOS])。\n",
        "        encoder_input, attn_mask = self.src_tokenizer.encode(\n",
        "            tokens_list,\n",
        "            add_bos=True,\n",
        "            add_eos=True,\n",
        "            return_mask=True,\n",
        "            )\n",
        "        encoder_input = torch.Tensor(encoder_input).to(dtype=torch.int64)\n",
        "        # 使用模型的 infer 方法对编码器输入进行推理，得到输出结果 outputs\n",
        "        outputs = model.infer(encoder_inputs=encoder_input, encoder_inputs_mask=attn_mask)\n",
        "\n",
        "        preds = outputs.preds.numpy()\n",
        "        # 使用目标语言的 trg_tokenizer 对预测序列进行解码，得到解码后的目标语言句子列表 trg_decoded。\n",
        "        trg_decoded = self.trg_tokenizer.decode(preds, split=True, remove_eos=False, remove_bos=False, remove_pad=False)\n",
        "        # 使用源语言的 src_tokenizer 对编码器输入进行解码，得到解码后的源语言句子列表 src_decoded。为下面绘制热力图做准备。\n",
        "        src_decoded = self.src_tokenizer.decode(\n",
        "            encoder_input.numpy(),\n",
        "            split=True,\n",
        "            remove_bos=False,\n",
        "            remove_eos=False\n",
        "            )\n",
        "\n",
        "        # post processed attn scores\n",
        "        # outputs.decoder_attentions[-1]  # the last layer of self-attention scores\n",
        "\n",
        "        # draw the attention map of the last decoder block\n",
        "        for attn_score, cross_attn_score, src, trg in zip(\n",
        "            outputs.decoder_attentions[layer_idx], outputs.cross_attentions[layer_idx], src_decoded, trg_decoded):\n",
        "            if heads_list is None:# 如果没有指定heads_list，就画单个热力图\n",
        "                self.draw_attention_map(\n",
        "                    attn_score,\n",
        "                    cross_attn_score,\n",
        "                    src,\n",
        "                    trg,\n",
        "                )\n",
        "            else:# 如果指定了heads_list，就画多个热力图\n",
        "                self.draw_attention_maps(\n",
        "                    attn_score,\n",
        "                    cross_attn_score,\n",
        "                    src,\n",
        "                    trg,\n",
        "                    heads_list=heads_list,\n",
        "                    )\n",
        "        return [self.mose_detokenizer.tokenize(self.pattern.sub(\"\", s).split()) for s in self.trg_tokenizer.decode(preds)] #将解码后的目标语言句子列表返回，并使用 mose_detokenizer 进行去标记化，最终得到翻译后的结果。\n",
        "\n",
        "\n",
        "# sentence_list = [\n",
        "#     \"Mann in einem kleinen weißen Boot auf einem See.\",  # Man in a small white boat on a lake.\n",
        "#     \"Ein Mann mit einem Eimer und ein Mädchen mit einem Hut am Strand.\", # A man with a bucket and a girl in a hat on the beach.\n",
        "#     \"Drei Männer auf Pferden während eines Rennens.\",  # Three men on horses during a race.\n",
        "#     \"Ein Mann und eine Frau essen zu Abend\",  # 一个男人和一个女人在吃晚餐\n",
        "# ]\n",
        "sentence_list = [\n",
        "    # \"Mann in einem kleinen weißen Boot auf einem See.\",  # Man in a small white boat on a lake.\n",
        "    \"Ein Mann mit einem Eimer und ein Mädchen mit einem Hut am Strand.\", # A man with a bucket and a girl in a hat on the beach.\n",
        "    # \"Drei Männer auf Pferden während eines Rennens.\",  # Three men on horses during a race.\n",
        "    # \"Ein Mann und eine Frau essen zu Abend\",  # 一个男人和一个女人在吃晚餐\n",
        "]\n",
        "\n",
        "# load checkpoints\n",
        "model = TransformerModel(config)\n",
        "model.load_state_dict(state_dict)\n",
        "translator = Translator(model.cpu(), tokenizer, tokenizer)\n",
        "translator(\n",
        "    sentence_list,\n",
        "    layer_idx=-1,\n",
        "    # heads_list=[0, 1, 2, 3, 4, 5, 6, 7]\n",
        "    )\n"
      ]
    }
  ],
  "metadata": {
    "accelerator": "GPU",
    "colab": {
      "gpuType": "L4",
      "machine_shape": "hm",
      "provenance": []
    },
    "kernelspec": {
      "display_name": "Python 3",
      "name": "python3"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3.12.3"
    },
    "widgets": {
      "application/vnd.jupyter.widget-state+json": {
        "046c17ba17f94587968cda8c761c2bf7": {
          "model_module": "@jupyter-widgets/base",
          "model_module_version": "1.2.0",
          "model_name": "LayoutModel",
          "state": {
            "_model_module": "@jupyter-widgets/base",
            "_model_module_version": "1.2.0",
            "_model_name": "LayoutModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "LayoutView",
            "align_content": null,
            "align_items": null,
            "align_self": null,
            "border": null,
            "bottom": null,
            "display": null,
            "flex": null,
            "flex_flow": null,
            "grid_area": null,
            "grid_auto_columns": null,
            "grid_auto_flow": null,
            "grid_auto_rows": null,
            "grid_column": null,
            "grid_gap": null,
            "grid_row": null,
            "grid_template_areas": null,
            "grid_template_columns": null,
            "grid_template_rows": null,
            "height": null,
            "justify_content": null,
            "justify_items": null,
            "left": null,
            "margin": null,
            "max_height": null,
            "max_width": null,
            "min_height": null,
            "min_width": null,
            "object_fit": null,
            "object_position": null,
            "order": null,
            "overflow": null,
            "overflow_x": null,
            "overflow_y": null,
            "padding": null,
            "right": null,
            "top": null,
            "visibility": null,
            "width": null
          }
        },
        "110a1f620812433692b0442ba588013c": {
          "model_module": "@jupyter-widgets/base",
          "model_module_version": "1.2.0",
          "model_name": "LayoutModel",
          "state": {
            "_model_module": "@jupyter-widgets/base",
            "_model_module_version": "1.2.0",
            "_model_name": "LayoutModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "LayoutView",
            "align_content": null,
            "align_items": null,
            "align_self": null,
            "border": null,
            "bottom": null,
            "display": null,
            "flex": null,
            "flex_flow": null,
            "grid_area": null,
            "grid_auto_columns": null,
            "grid_auto_flow": null,
            "grid_auto_rows": null,
            "grid_column": null,
            "grid_gap": null,
            "grid_row": null,
            "grid_template_areas": null,
            "grid_template_columns": null,
            "grid_template_rows": null,
            "height": null,
            "justify_content": null,
            "justify_items": null,
            "left": null,
            "margin": null,
            "max_height": null,
            "max_width": null,
            "min_height": null,
            "min_width": null,
            "object_fit": null,
            "object_position": null,
            "order": null,
            "overflow": null,
            "overflow_x": null,
            "overflow_y": null,
            "padding": null,
            "right": null,
            "top": null,
            "visibility": null,
            "width": null
          }
        },
        "114607d303c64d558617e41975b25270": {
          "model_module": "@jupyter-widgets/base",
          "model_module_version": "1.2.0",
          "model_name": "LayoutModel",
          "state": {
            "_model_module": "@jupyter-widgets/base",
            "_model_module_version": "1.2.0",
            "_model_name": "LayoutModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "LayoutView",
            "align_content": null,
            "align_items": null,
            "align_self": null,
            "border": null,
            "bottom": null,
            "display": null,
            "flex": null,
            "flex_flow": null,
            "grid_area": null,
            "grid_auto_columns": null,
            "grid_auto_flow": null,
            "grid_auto_rows": null,
            "grid_column": null,
            "grid_gap": null,
            "grid_row": null,
            "grid_template_areas": null,
            "grid_template_columns": null,
            "grid_template_rows": null,
            "height": null,
            "justify_content": null,
            "justify_items": null,
            "left": null,
            "margin": null,
            "max_height": null,
            "max_width": null,
            "min_height": null,
            "min_width": null,
            "object_fit": null,
            "object_position": null,
            "order": null,
            "overflow": null,
            "overflow_x": null,
            "overflow_y": null,
            "padding": null,
            "right": null,
            "top": null,
            "visibility": null,
            "width": null
          }
        },
        "16ae7acad596458890f112a68c515cdf": {
          "model_module": "@jupyter-widgets/controls",
          "model_module_version": "1.5.0",
          "model_name": "HTMLModel",
          "state": {
            "_dom_classes": [],
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "HTMLModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/controls",
            "_view_module_version": "1.5.0",
            "_view_name": "HTMLView",
            "description": "",
            "description_tooltip": null,
            "layout": "IPY_MODEL_ec9417d5c4e54d18966e0140e60e4f7e",
            "placeholder": "​",
            "style": "IPY_MODEL_2d5c3abf516b48b6946778709ac9d97d",
            "value": " 16/128 [00:00&lt;00:01, 68.16it/s]"
          }
        },
        "17b7154badac4cae83ae11e0bbc8f881": {
          "model_module": "@jupyter-widgets/controls",
          "model_module_version": "1.5.0",
          "model_name": "DescriptionStyleModel",
          "state": {
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "DescriptionStyleModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "StyleView",
            "description_width": ""
          }
        },
        "260f33f2bfc745cf904790692b45daa3": {
          "model_module": "@jupyter-widgets/base",
          "model_module_version": "1.2.0",
          "model_name": "LayoutModel",
          "state": {
            "_model_module": "@jupyter-widgets/base",
            "_model_module_version": "1.2.0",
            "_model_name": "LayoutModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "LayoutView",
            "align_content": null,
            "align_items": null,
            "align_self": null,
            "border": null,
            "bottom": null,
            "display": null,
            "flex": null,
            "flex_flow": null,
            "grid_area": null,
            "grid_auto_columns": null,
            "grid_auto_flow": null,
            "grid_auto_rows": null,
            "grid_column": null,
            "grid_gap": null,
            "grid_row": null,
            "grid_template_areas": null,
            "grid_template_columns": null,
            "grid_template_rows": null,
            "height": null,
            "justify_content": null,
            "justify_items": null,
            "left": null,
            "margin": null,
            "max_height": null,
            "max_width": null,
            "min_height": null,
            "min_width": null,
            "object_fit": null,
            "object_position": null,
            "order": null,
            "overflow": null,
            "overflow_x": null,
            "overflow_y": null,
            "padding": null,
            "right": null,
            "top": null,
            "visibility": null,
            "width": null
          }
        },
        "280b011dc683465985da449bc80ab71f": {
          "model_module": "@jupyter-widgets/controls",
          "model_module_version": "1.5.0",
          "model_name": "FloatProgressModel",
          "state": {
            "_dom_classes": [],
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "FloatProgressModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/controls",
            "_view_module_version": "1.5.0",
            "_view_name": "ProgressView",
            "bar_style": "danger",
            "description": "",
            "description_tooltip": null,
            "layout": "IPY_MODEL_046c17ba17f94587968cda8c761c2bf7",
            "max": 128,
            "min": 0,
            "orientation": "horizontal",
            "style": "IPY_MODEL_79a55387adba484e9485779a07bcc8e9",
            "value": 16
          }
        },
        "2d5c3abf516b48b6946778709ac9d97d": {
          "model_module": "@jupyter-widgets/controls",
          "model_module_version": "1.5.0",
          "model_name": "DescriptionStyleModel",
          "state": {
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "DescriptionStyleModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "StyleView",
            "description_width": ""
          }
        },
        "3212f3a98f5e4a96ac888f368f4fff42": {
          "model_module": "@jupyter-widgets/controls",
          "model_module_version": "1.5.0",
          "model_name": "HBoxModel",
          "state": {
            "_dom_classes": [],
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "HBoxModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/controls",
            "_view_module_version": "1.5.0",
            "_view_name": "HBoxView",
            "box_style": "",
            "children": [
              "IPY_MODEL_8af2647d8486443a8a025bc30e9ddac6",
              "IPY_MODEL_280b011dc683465985da449bc80ab71f",
              "IPY_MODEL_16ae7acad596458890f112a68c515cdf"
            ],
            "layout": "IPY_MODEL_f6971c6f2b22427cb2b58ffffda71135"
          }
        },
        "32ab830293104d33b6f584b0ed030aeb": {
          "model_module": "@jupyter-widgets/controls",
          "model_module_version": "1.5.0",
          "model_name": "DescriptionStyleModel",
          "state": {
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "DescriptionStyleModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "StyleView",
            "description_width": ""
          }
        },
        "381277e910d647b98475c7e514d4ce59": {
          "model_module": "@jupyter-widgets/controls",
          "model_module_version": "1.5.0",
          "model_name": "HBoxModel",
          "state": {
            "_dom_classes": [],
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "HBoxModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/controls",
            "_view_module_version": "1.5.0",
            "_view_name": "HBoxView",
            "box_style": "",
            "children": [
              "IPY_MODEL_79e7a2f67e704862b46c4479a28aa57e",
              "IPY_MODEL_530f7729ef174321868689c813cbab16",
              "IPY_MODEL_6ceb216821134bffaacd542be9332afd"
            ],
            "layout": "IPY_MODEL_b4f510c9bb9144ccb2fb6381ad2959b1"
          }
        },
        "3a96896a8b1746b08d855322fc274a7c": {
          "model_module": "@jupyter-widgets/controls",
          "model_module_version": "1.5.0",
          "model_name": "DescriptionStyleModel",
          "state": {
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "DescriptionStyleModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "StyleView",
            "description_width": ""
          }
        },
        "4111b8dea92d4c73a0d797c900d1c4e4": {
          "model_module": "@jupyter-widgets/controls",
          "model_module_version": "1.5.0",
          "model_name": "HTMLModel",
          "state": {
            "_dom_classes": [],
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "HTMLModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/controls",
            "_view_module_version": "1.5.0",
            "_view_name": "HTMLView",
            "description": "",
            "description_tooltip": null,
            "layout": "IPY_MODEL_e78c6667146541fdb695db5690fa4301",
            "placeholder": "​",
            "style": "IPY_MODEL_17b7154badac4cae83ae11e0bbc8f881",
            "value": " 18107/18107 [00:00&lt;00:00, 661449.10it/s]"
          }
        },
        "512ed7c39b0a49ed97c4ed9aa9cb47e9": {
          "model_module": "@jupyter-widgets/controls",
          "model_module_version": "1.5.0",
          "model_name": "ProgressStyleModel",
          "state": {
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "ProgressStyleModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "StyleView",
            "bar_color": null,
            "description_width": ""
          }
        },
        "530f7729ef174321868689c813cbab16": {
          "model_module": "@jupyter-widgets/controls",
          "model_module_version": "1.5.0",
          "model_name": "FloatProgressModel",
          "state": {
            "_dom_classes": [],
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "FloatProgressModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/controls",
            "_view_module_version": "1.5.0",
            "_view_name": "ProgressView",
            "bar_style": "success",
            "description": "",
            "description_tooltip": null,
            "layout": "IPY_MODEL_da3d1cec9148455ea084b22d7209805e",
            "max": 1,
            "min": 0,
            "orientation": "horizontal",
            "style": "IPY_MODEL_512ed7c39b0a49ed97c4ed9aa9cb47e9",
            "value": 1
          }
        },
        "56b020a70cd34c1c9673d7ebdba23c43": {
          "model_module": "@jupyter-widgets/controls",
          "model_module_version": "1.5.0",
          "model_name": "DescriptionStyleModel",
          "state": {
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "DescriptionStyleModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "StyleView",
            "description_width": ""
          }
        },
        "5b30c15446eb4a6cbc62498fb6753323": {
          "model_module": "@jupyter-widgets/controls",
          "model_module_version": "1.5.0",
          "model_name": "DescriptionStyleModel",
          "state": {
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "DescriptionStyleModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "StyleView",
            "description_width": ""
          }
        },
        "6ada793910ae47b0953f6be510d7d935": {
          "model_module": "@jupyter-widgets/base",
          "model_module_version": "1.2.0",
          "model_name": "LayoutModel",
          "state": {
            "_model_module": "@jupyter-widgets/base",
            "_model_module_version": "1.2.0",
            "_model_name": "LayoutModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "LayoutView",
            "align_content": null,
            "align_items": null,
            "align_self": null,
            "border": null,
            "bottom": null,
            "display": null,
            "flex": null,
            "flex_flow": null,
            "grid_area": null,
            "grid_auto_columns": null,
            "grid_auto_flow": null,
            "grid_auto_rows": null,
            "grid_column": null,
            "grid_gap": null,
            "grid_row": null,
            "grid_template_areas": null,
            "grid_template_columns": null,
            "grid_template_rows": null,
            "height": null,
            "justify_content": null,
            "justify_items": null,
            "left": null,
            "margin": null,
            "max_height": null,
            "max_width": null,
            "min_height": null,
            "min_width": null,
            "object_fit": null,
            "object_position": null,
            "order": null,
            "overflow": null,
            "overflow_x": null,
            "overflow_y": null,
            "padding": null,
            "right": null,
            "top": null,
            "visibility": null,
            "width": null
          }
        },
        "6ceb216821134bffaacd542be9332afd": {
          "model_module": "@jupyter-widgets/controls",
          "model_module_version": "1.5.0",
          "model_name": "HTMLModel",
          "state": {
            "_dom_classes": [],
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "HTMLModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/controls",
            "_view_module_version": "1.5.0",
            "_view_name": "HTMLView",
            "description": "",
            "description_tooltip": null,
            "layout": "IPY_MODEL_6ada793910ae47b0953f6be510d7d935",
            "placeholder": "​",
            "style": "IPY_MODEL_7045995d4587482c8d87797846e13ad9",
            "value": " 966/? [00:16&lt;00:00, 56.13it/s]"
          }
        },
        "7045995d4587482c8d87797846e13ad9": {
          "model_module": "@jupyter-widgets/controls",
          "model_module_version": "1.5.0",
          "model_name": "DescriptionStyleModel",
          "state": {
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "DescriptionStyleModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "StyleView",
            "description_width": ""
          }
        },
        "79a55387adba484e9485779a07bcc8e9": {
          "model_module": "@jupyter-widgets/controls",
          "model_module_version": "1.5.0",
          "model_name": "ProgressStyleModel",
          "state": {
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "ProgressStyleModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "StyleView",
            "bar_color": null,
            "description_width": ""
          }
        },
        "79e7a2f67e704862b46c4479a28aa57e": {
          "model_module": "@jupyter-widgets/controls",
          "model_module_version": "1.5.0",
          "model_name": "HTMLModel",
          "state": {
            "_dom_classes": [],
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "HTMLModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/controls",
            "_view_module_version": "1.5.0",
            "_view_name": "HTMLView",
            "description": "",
            "description_tooltip": null,
            "layout": "IPY_MODEL_260f33f2bfc745cf904790692b45daa3",
            "placeholder": "​",
            "style": "IPY_MODEL_3a96896a8b1746b08d855322fc274a7c",
            "value": ""
          }
        },
        "7d1e98340eb54ca7be701aba5cf76943": {
          "model_module": "@jupyter-widgets/base",
          "model_module_version": "1.2.0",
          "model_name": "LayoutModel",
          "state": {
            "_model_module": "@jupyter-widgets/base",
            "_model_module_version": "1.2.0",
            "_model_name": "LayoutModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "LayoutView",
            "align_content": null,
            "align_items": null,
            "align_self": null,
            "border": null,
            "bottom": null,
            "display": null,
            "flex": null,
            "flex_flow": null,
            "grid_area": null,
            "grid_auto_columns": null,
            "grid_auto_flow": null,
            "grid_auto_rows": null,
            "grid_column": null,
            "grid_gap": null,
            "grid_row": null,
            "grid_template_areas": null,
            "grid_template_columns": null,
            "grid_template_rows": null,
            "height": null,
            "justify_content": null,
            "justify_items": null,
            "left": null,
            "margin": null,
            "max_height": null,
            "max_width": null,
            "min_height": null,
            "min_width": null,
            "object_fit": null,
            "object_position": null,
            "order": null,
            "overflow": null,
            "overflow_x": null,
            "overflow_y": null,
            "padding": null,
            "right": null,
            "top": null,
            "visibility": null,
            "width": null
          }
        },
        "7fff264309184763be76c74febde5af1": {
          "model_module": "@jupyter-widgets/controls",
          "model_module_version": "1.5.0",
          "model_name": "HBoxModel",
          "state": {
            "_dom_classes": [],
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "HBoxModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/controls",
            "_view_module_version": "1.5.0",
            "_view_name": "HBoxView",
            "box_style": "",
            "children": [
              "IPY_MODEL_a51848bc90674b5bbfe6aa10b1fbd92b",
              "IPY_MODEL_f713cc5ab93e467699537e1033853259",
              "IPY_MODEL_880ed6db148b41fe93ccf987173c95b0"
            ],
            "layout": "IPY_MODEL_b0af4291ebd44162bc27b36c1ad3f651"
          }
        },
        "8271841f536f476fa7f168285169b8b0": {
          "model_module": "@jupyter-widgets/controls",
          "model_module_version": "1.5.0",
          "model_name": "HBoxModel",
          "state": {
            "_dom_classes": [],
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "HBoxModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/controls",
            "_view_module_version": "1.5.0",
            "_view_name": "HBoxView",
            "box_style": "",
            "children": [
              "IPY_MODEL_d04403d6d9de45229ab199c84d8e78b1",
              "IPY_MODEL_83516e53d8044b5984c31b0cfa983454",
              "IPY_MODEL_4111b8dea92d4c73a0d797c900d1c4e4"
            ],
            "layout": "IPY_MODEL_110a1f620812433692b0442ba588013c"
          }
        },
        "83516e53d8044b5984c31b0cfa983454": {
          "model_module": "@jupyter-widgets/controls",
          "model_module_version": "1.5.0",
          "model_name": "FloatProgressModel",
          "state": {
            "_dom_classes": [],
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "FloatProgressModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/controls",
            "_view_module_version": "1.5.0",
            "_view_name": "ProgressView",
            "bar_style": "success",
            "description": "",
            "description_tooltip": null,
            "layout": "IPY_MODEL_114607d303c64d558617e41975b25270",
            "max": 18107,
            "min": 0,
            "orientation": "horizontal",
            "style": "IPY_MODEL_9aca93d3cde5487c8d83e9007673f227",
            "value": 18107
          }
        },
        "880ed6db148b41fe93ccf987173c95b0": {
          "model_module": "@jupyter-widgets/controls",
          "model_module_version": "1.5.0",
          "model_name": "HTMLModel",
          "state": {
            "_dom_classes": [],
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "HTMLModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/controls",
            "_view_module_version": "1.5.0",
            "_view_name": "HTMLView",
            "description": "",
            "description_tooltip": null,
            "layout": "IPY_MODEL_928f41cfb6184310afb07d861c17a413",
            "placeholder": "​",
            "style": "IPY_MODEL_91c3e9b25c94440181ce6e679ef357c3",
            "value": " 17160/17160 [22:53&lt;00:00, 12.60it/s, epoch=39, loss=2.22, val_loss=3.3]"
          }
        },
        "8af2647d8486443a8a025bc30e9ddac6": {
          "model_module": "@jupyter-widgets/controls",
          "model_module_version": "1.5.0",
          "model_name": "HTMLModel",
          "state": {
            "_dom_classes": [],
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "HTMLModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/controls",
            "_view_module_version": "1.5.0",
            "_view_name": "HTMLView",
            "description": "",
            "description_tooltip": null,
            "layout": "IPY_MODEL_d939b58e958641bdb4f2a2accc1c3645",
            "placeholder": "​",
            "style": "IPY_MODEL_5b30c15446eb4a6cbc62498fb6753323",
            "value": " 12%"
          }
        },
        "91c3e9b25c94440181ce6e679ef357c3": {
          "model_module": "@jupyter-widgets/controls",
          "model_module_version": "1.5.0",
          "model_name": "DescriptionStyleModel",
          "state": {
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "DescriptionStyleModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "StyleView",
            "description_width": ""
          }
        },
        "928f41cfb6184310afb07d861c17a413": {
          "model_module": "@jupyter-widgets/base",
          "model_module_version": "1.2.0",
          "model_name": "LayoutModel",
          "state": {
            "_model_module": "@jupyter-widgets/base",
            "_model_module_version": "1.2.0",
            "_model_name": "LayoutModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "LayoutView",
            "align_content": null,
            "align_items": null,
            "align_self": null,
            "border": null,
            "bottom": null,
            "display": null,
            "flex": null,
            "flex_flow": null,
            "grid_area": null,
            "grid_auto_columns": null,
            "grid_auto_flow": null,
            "grid_auto_rows": null,
            "grid_column": null,
            "grid_gap": null,
            "grid_row": null,
            "grid_template_areas": null,
            "grid_template_columns": null,
            "grid_template_rows": null,
            "height": null,
            "justify_content": null,
            "justify_items": null,
            "left": null,
            "margin": null,
            "max_height": null,
            "max_width": null,
            "min_height": null,
            "min_width": null,
            "object_fit": null,
            "object_position": null,
            "order": null,
            "overflow": null,
            "overflow_x": null,
            "overflow_y": null,
            "padding": null,
            "right": null,
            "top": null,
            "visibility": null,
            "width": null
          }
        },
        "9aca93d3cde5487c8d83e9007673f227": {
          "model_module": "@jupyter-widgets/controls",
          "model_module_version": "1.5.0",
          "model_name": "ProgressStyleModel",
          "state": {
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "ProgressStyleModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "StyleView",
            "bar_color": null,
            "description_width": ""
          }
        },
        "a51848bc90674b5bbfe6aa10b1fbd92b": {
          "model_module": "@jupyter-widgets/controls",
          "model_module_version": "1.5.0",
          "model_name": "HTMLModel",
          "state": {
            "_dom_classes": [],
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "HTMLModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/controls",
            "_view_module_version": "1.5.0",
            "_view_name": "HTMLView",
            "description": "",
            "description_tooltip": null,
            "layout": "IPY_MODEL_eac3d467f0e24fc5a461c4f5037d76da",
            "placeholder": "​",
            "style": "IPY_MODEL_56b020a70cd34c1c9673d7ebdba23c43",
            "value": "100%"
          }
        },
        "a81f6c3bb6a4482b86d028d608b04559": {
          "model_module": "@jupyter-widgets/base",
          "model_module_version": "1.2.0",
          "model_name": "LayoutModel",
          "state": {
            "_model_module": "@jupyter-widgets/base",
            "_model_module_version": "1.2.0",
            "_model_name": "LayoutModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "LayoutView",
            "align_content": null,
            "align_items": null,
            "align_self": null,
            "border": null,
            "bottom": null,
            "display": null,
            "flex": null,
            "flex_flow": null,
            "grid_area": null,
            "grid_auto_columns": null,
            "grid_auto_flow": null,
            "grid_auto_rows": null,
            "grid_column": null,
            "grid_gap": null,
            "grid_row": null,
            "grid_template_areas": null,
            "grid_template_columns": null,
            "grid_template_rows": null,
            "height": null,
            "justify_content": null,
            "justify_items": null,
            "left": null,
            "margin": null,
            "max_height": null,
            "max_width": null,
            "min_height": null,
            "min_width": null,
            "object_fit": null,
            "object_position": null,
            "order": null,
            "overflow": null,
            "overflow_x": null,
            "overflow_y": null,
            "padding": null,
            "right": null,
            "top": null,
            "visibility": null,
            "width": null
          }
        },
        "b0af4291ebd44162bc27b36c1ad3f651": {
          "model_module": "@jupyter-widgets/base",
          "model_module_version": "1.2.0",
          "model_name": "LayoutModel",
          "state": {
            "_model_module": "@jupyter-widgets/base",
            "_model_module_version": "1.2.0",
            "_model_name": "LayoutModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "LayoutView",
            "align_content": null,
            "align_items": null,
            "align_self": null,
            "border": null,
            "bottom": null,
            "display": null,
            "flex": null,
            "flex_flow": null,
            "grid_area": null,
            "grid_auto_columns": null,
            "grid_auto_flow": null,
            "grid_auto_rows": null,
            "grid_column": null,
            "grid_gap": null,
            "grid_row": null,
            "grid_template_areas": null,
            "grid_template_columns": null,
            "grid_template_rows": null,
            "height": null,
            "justify_content": null,
            "justify_items": null,
            "left": null,
            "margin": null,
            "max_height": null,
            "max_width": null,
            "min_height": null,
            "min_width": null,
            "object_fit": null,
            "object_position": null,
            "order": null,
            "overflow": null,
            "overflow_x": null,
            "overflow_y": null,
            "padding": null,
            "right": null,
            "top": null,
            "visibility": null,
            "width": null
          }
        },
        "b4f510c9bb9144ccb2fb6381ad2959b1": {
          "model_module": "@jupyter-widgets/base",
          "model_module_version": "1.2.0",
          "model_name": "LayoutModel",
          "state": {
            "_model_module": "@jupyter-widgets/base",
            "_model_module_version": "1.2.0",
            "_model_name": "LayoutModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "LayoutView",
            "align_content": null,
            "align_items": null,
            "align_self": null,
            "border": null,
            "bottom": null,
            "display": null,
            "flex": null,
            "flex_flow": null,
            "grid_area": null,
            "grid_auto_columns": null,
            "grid_auto_flow": null,
            "grid_auto_rows": null,
            "grid_column": null,
            "grid_gap": null,
            "grid_row": null,
            "grid_template_areas": null,
            "grid_template_columns": null,
            "grid_template_rows": null,
            "height": null,
            "justify_content": null,
            "justify_items": null,
            "left": null,
            "margin": null,
            "max_height": null,
            "max_width": null,
            "min_height": null,
            "min_width": null,
            "object_fit": null,
            "object_position": null,
            "order": null,
            "overflow": null,
            "overflow_x": null,
            "overflow_y": null,
            "padding": null,
            "right": null,
            "top": null,
            "visibility": null,
            "width": null
          }
        },
        "d04403d6d9de45229ab199c84d8e78b1": {
          "model_module": "@jupyter-widgets/controls",
          "model_module_version": "1.5.0",
          "model_name": "HTMLModel",
          "state": {
            "_dom_classes": [],
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "HTMLModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/controls",
            "_view_module_version": "1.5.0",
            "_view_name": "HTMLView",
            "description": "",
            "description_tooltip": null,
            "layout": "IPY_MODEL_a81f6c3bb6a4482b86d028d608b04559",
            "placeholder": "​",
            "style": "IPY_MODEL_32ab830293104d33b6f584b0ed030aeb",
            "value": "100%"
          }
        },
        "d3ac645daf904649988e69aa58fb665a": {
          "model_module": "@jupyter-widgets/controls",
          "model_module_version": "1.5.0",
          "model_name": "ProgressStyleModel",
          "state": {
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "ProgressStyleModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "StyleView",
            "bar_color": null,
            "description_width": ""
          }
        },
        "d939b58e958641bdb4f2a2accc1c3645": {
          "model_module": "@jupyter-widgets/base",
          "model_module_version": "1.2.0",
          "model_name": "LayoutModel",
          "state": {
            "_model_module": "@jupyter-widgets/base",
            "_model_module_version": "1.2.0",
            "_model_name": "LayoutModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "LayoutView",
            "align_content": null,
            "align_items": null,
            "align_self": null,
            "border": null,
            "bottom": null,
            "display": null,
            "flex": null,
            "flex_flow": null,
            "grid_area": null,
            "grid_auto_columns": null,
            "grid_auto_flow": null,
            "grid_auto_rows": null,
            "grid_column": null,
            "grid_gap": null,
            "grid_row": null,
            "grid_template_areas": null,
            "grid_template_columns": null,
            "grid_template_rows": null,
            "height": null,
            "justify_content": null,
            "justify_items": null,
            "left": null,
            "margin": null,
            "max_height": null,
            "max_width": null,
            "min_height": null,
            "min_width": null,
            "object_fit": null,
            "object_position": null,
            "order": null,
            "overflow": null,
            "overflow_x": null,
            "overflow_y": null,
            "padding": null,
            "right": null,
            "top": null,
            "visibility": null,
            "width": null
          }
        },
        "da3d1cec9148455ea084b22d7209805e": {
          "model_module": "@jupyter-widgets/base",
          "model_module_version": "1.2.0",
          "model_name": "LayoutModel",
          "state": {
            "_model_module": "@jupyter-widgets/base",
            "_model_module_version": "1.2.0",
            "_model_name": "LayoutModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "LayoutView",
            "align_content": null,
            "align_items": null,
            "align_self": null,
            "border": null,
            "bottom": null,
            "display": null,
            "flex": null,
            "flex_flow": null,
            "grid_area": null,
            "grid_auto_columns": null,
            "grid_auto_flow": null,
            "grid_auto_rows": null,
            "grid_column": null,
            "grid_gap": null,
            "grid_row": null,
            "grid_template_areas": null,
            "grid_template_columns": null,
            "grid_template_rows": null,
            "height": null,
            "justify_content": null,
            "justify_items": null,
            "left": null,
            "margin": null,
            "max_height": null,
            "max_width": null,
            "min_height": null,
            "min_width": null,
            "object_fit": null,
            "object_position": null,
            "order": null,
            "overflow": null,
            "overflow_x": null,
            "overflow_y": null,
            "padding": null,
            "right": null,
            "top": null,
            "visibility": null,
            "width": "20px"
          }
        },
        "e78c6667146541fdb695db5690fa4301": {
          "model_module": "@jupyter-widgets/base",
          "model_module_version": "1.2.0",
          "model_name": "LayoutModel",
          "state": {
            "_model_module": "@jupyter-widgets/base",
            "_model_module_version": "1.2.0",
            "_model_name": "LayoutModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "LayoutView",
            "align_content": null,
            "align_items": null,
            "align_self": null,
            "border": null,
            "bottom": null,
            "display": null,
            "flex": null,
            "flex_flow": null,
            "grid_area": null,
            "grid_auto_columns": null,
            "grid_auto_flow": null,
            "grid_auto_rows": null,
            "grid_column": null,
            "grid_gap": null,
            "grid_row": null,
            "grid_template_areas": null,
            "grid_template_columns": null,
            "grid_template_rows": null,
            "height": null,
            "justify_content": null,
            "justify_items": null,
            "left": null,
            "margin": null,
            "max_height": null,
            "max_width": null,
            "min_height": null,
            "min_width": null,
            "object_fit": null,
            "object_position": null,
            "order": null,
            "overflow": null,
            "overflow_x": null,
            "overflow_y": null,
            "padding": null,
            "right": null,
            "top": null,
            "visibility": null,
            "width": null
          }
        },
        "eac3d467f0e24fc5a461c4f5037d76da": {
          "model_module": "@jupyter-widgets/base",
          "model_module_version": "1.2.0",
          "model_name": "LayoutModel",
          "state": {
            "_model_module": "@jupyter-widgets/base",
            "_model_module_version": "1.2.0",
            "_model_name": "LayoutModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "LayoutView",
            "align_content": null,
            "align_items": null,
            "align_self": null,
            "border": null,
            "bottom": null,
            "display": null,
            "flex": null,
            "flex_flow": null,
            "grid_area": null,
            "grid_auto_columns": null,
            "grid_auto_flow": null,
            "grid_auto_rows": null,
            "grid_column": null,
            "grid_gap": null,
            "grid_row": null,
            "grid_template_areas": null,
            "grid_template_columns": null,
            "grid_template_rows": null,
            "height": null,
            "justify_content": null,
            "justify_items": null,
            "left": null,
            "margin": null,
            "max_height": null,
            "max_width": null,
            "min_height": null,
            "min_width": null,
            "object_fit": null,
            "object_position": null,
            "order": null,
            "overflow": null,
            "overflow_x": null,
            "overflow_y": null,
            "padding": null,
            "right": null,
            "top": null,
            "visibility": null,
            "width": null
          }
        },
        "ec9417d5c4e54d18966e0140e60e4f7e": {
          "model_module": "@jupyter-widgets/base",
          "model_module_version": "1.2.0",
          "model_name": "LayoutModel",
          "state": {
            "_model_module": "@jupyter-widgets/base",
            "_model_module_version": "1.2.0",
            "_model_name": "LayoutModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "LayoutView",
            "align_content": null,
            "align_items": null,
            "align_self": null,
            "border": null,
            "bottom": null,
            "display": null,
            "flex": null,
            "flex_flow": null,
            "grid_area": null,
            "grid_auto_columns": null,
            "grid_auto_flow": null,
            "grid_auto_rows": null,
            "grid_column": null,
            "grid_gap": null,
            "grid_row": null,
            "grid_template_areas": null,
            "grid_template_columns": null,
            "grid_template_rows": null,
            "height": null,
            "justify_content": null,
            "justify_items": null,
            "left": null,
            "margin": null,
            "max_height": null,
            "max_width": null,
            "min_height": null,
            "min_width": null,
            "object_fit": null,
            "object_position": null,
            "order": null,
            "overflow": null,
            "overflow_x": null,
            "overflow_y": null,
            "padding": null,
            "right": null,
            "top": null,
            "visibility": null,
            "width": null
          }
        },
        "f6971c6f2b22427cb2b58ffffda71135": {
          "model_module": "@jupyter-widgets/base",
          "model_module_version": "1.2.0",
          "model_name": "LayoutModel",
          "state": {
            "_model_module": "@jupyter-widgets/base",
            "_model_module_version": "1.2.0",
            "_model_name": "LayoutModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "LayoutView",
            "align_content": null,
            "align_items": null,
            "align_self": null,
            "border": null,
            "bottom": null,
            "display": null,
            "flex": null,
            "flex_flow": null,
            "grid_area": null,
            "grid_auto_columns": null,
            "grid_auto_flow": null,
            "grid_auto_rows": null,
            "grid_column": null,
            "grid_gap": null,
            "grid_row": null,
            "grid_template_areas": null,
            "grid_template_columns": null,
            "grid_template_rows": null,
            "height": null,
            "justify_content": null,
            "justify_items": null,
            "left": null,
            "margin": null,
            "max_height": null,
            "max_width": null,
            "min_height": null,
            "min_width": null,
            "object_fit": null,
            "object_position": null,
            "order": null,
            "overflow": null,
            "overflow_x": null,
            "overflow_y": null,
            "padding": null,
            "right": null,
            "top": null,
            "visibility": null,
            "width": null
          }
        },
        "f713cc5ab93e467699537e1033853259": {
          "model_module": "@jupyter-widgets/controls",
          "model_module_version": "1.5.0",
          "model_name": "FloatProgressModel",
          "state": {
            "_dom_classes": [],
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "FloatProgressModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/controls",
            "_view_module_version": "1.5.0",
            "_view_name": "ProgressView",
            "bar_style": "success",
            "description": "",
            "description_tooltip": null,
            "layout": "IPY_MODEL_7d1e98340eb54ca7be701aba5cf76943",
            "max": 17160,
            "min": 0,
            "orientation": "horizontal",
            "style": "IPY_MODEL_d3ac645daf904649988e69aa58fb665a",
            "value": 17160
          }
        }
      }
    }
  },
  "nbformat": 4,
  "nbformat_minor": 5
}
